เพิ่มสตริงคำนำหน้าเพื่อเริ่มต้นของแต่ละบรรทัด


334

ฉันมีไฟล์ดังนี้:

line1
line2
line3

และฉันต้องการได้รับ:

prefixline1
prefixline2
prefixline3

ฉันสามารถเขียนสคริปต์ Ruby แต่ดีกว่าถ้าฉันไม่ต้องการ

prefix/จะมี มันเป็นเส้นทาง/opt/workdir/ตัวอย่างเช่น

คำตอบ:


527
# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file

# If you want to create a new file
sed -e 's/^/prefix/' file > file.new

หากprefixมี/คุณสามารถใช้ตัวละครอื่น ๆ ที่ไม่ได้อยู่ในprefixนั้นหรือหลบหนีไป/ดังนั้นsedคำสั่งจะกลายเป็น

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'

1
@benjamin ฉันได้ตอบโต้คำตอบของคุณแล้ว แต่ฉันชอบsedงานเบา ๆ เช่นนี้ หากรู้ว่า "คำนำหน้า" เป็นเรื่องง่ายมากในการเลือกอักขระที่ไม่ได้มาจาก "คำนำหน้า"
Alok Singhal

1
อย่าลืมคุณยังสามารถใช้ในท่อเช่นsed foo | sed -e 's/^/x /' | bar
zigg

1
@ ดาตามันเท่ อีกวิธีหนึ่งก็sed -e '2,$s/^/prefix/'คือ
Alok Singhal

1
@BinChen หนีสิ่งที่/ชอบ\/(ในสตริงที่ยกมาเดี่ยว) หรือ\\/(ในสตริงที่ยกมาสองครั้ง)

8
ใช้sed -e 's/$/postfix/' fileหากคุณต้องการเพิ่มสตริงที่ส่วนท้ายของแต่ละบรรทัด
Brian

121
awk '$0="prefix"$0' file > new_file

ด้วย Perl (แทนที่ด้วย):

perl -pi 's/^/prefix/' file

8
ด้วยprtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ไพพ์

2
ด้วยไฟล์ขนาดใหญ่ (12 G) awkรายงานawk: out of memory in readrec 1 source line number 1แต่การแก้ปัญหาด้วยsedเสร็จสมบูรณ์แล้ว
jrm

33

คุณสามารถใช้ Vim ในโหมด Ex:

ex -sc '%s/^/prefix/|x' file
  1. % เลือกทุกบรรทัด

  2. s แทนที่

  3. x บันทึกและปิด


1
สำหรับฉันฉันเพิ่งเปิดไฟล์ในประเภทและประเภท:%s/^/prefix/เนื่องจากกลยุทธ์นี้จบลงด้วยการเป็นประโยชน์ในหลาย ๆ สถานการณ์
Frank Bryce

23

หากคำนำหน้าของคุณซับซ้อนเล็กน้อยให้ใส่ไว้ในตัวแปร:

prefix=path/to/file/

จากนั้นคุณผ่านตัวแปรนั้นและปล่อยให้ awk จัดการกับมัน

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt



5

นี่เป็นโซลูชันtsออนไลเนอร์ที่สามารถอ่านได้สูงโดยใช้คำสั่งจาก moreutils

$ cat file | ts prefix | tr -d ' '

และมันเป็นวิธีที่ได้รับทีละขั้นตอน:

# Step 0. create the file

$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line

$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle

$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3

'ts' ไม่ได้ถูกติดตั้งไว้ใน Linux distros เป็นจำนวนมาก นอกจากนี้การลดลงเนื่องจากการลาก "tr -d ''" ในคำตอบนี้จะลบช่องว่างทั้งหมดออกจากบรรทัดไม่ใช่เฉพาะพื้นที่ที่เพิ่มโดย 'ts'
Tim Bird

3

ในขณะที่ฉันไม่คิดว่า Pierr มีข้อกังวลใจนี้ฉันต้องการโซลูชันที่จะไม่หน่วงเวลาเอาต์พุตจากส่วน "สด" ของไฟล์เนื่องจากฉันต้องการตรวจสอบบันทึกการแจ้งเตือนหลายรายการพร้อมกันโดยนำหน้าแต่ละบรรทัดด้วยชื่อของบันทึกที่เกี่ยวข้อง .

น่าเสียดายที่ sed ตัดและแนะนำการบัฟเฟอร์มากเกินไปและทำให้ฉันไม่เห็นบรรทัดปัจจุบันมากที่สุด ข้อเสนอแนะของ Steven Penny ในการใช้-sตัวเลือกnlนั้นน่าสนใจและการทดสอบพิสูจน์ว่ามันไม่ได้แนะนำการบัฟเฟอร์ที่ไม่ต้องการที่เกี่ยวข้องกับฉัน

แม้ว่าจะมีปัญหาในการใช้งานสองสามประการnlที่เกี่ยวข้องกับความต้องการที่จะตัดหมายเลขบรรทัดที่ไม่ต้องการออก (แม้ว่าคุณจะไม่สนใจเกี่ยวกับสุนทรียภาพของมัน แต่อาจมีบางกรณีที่การใช้คอลัมน์พิเศษจะไม่เป็นที่ต้องการ) ขั้นแรกให้ใช้ "ตัด" เพื่อตัดตัวเลขออกใหม่แนะนำปัญหาบัฟเฟอร์ดังนั้นจึงทำให้การแก้ปัญหาเสียหาย ข้อที่สองการใช้ "-w1" ไม่ได้ช่วยเนื่องจากจะไม่ จำกัด จำนวนบรรทัดในคอลัมน์เดียว - มันจะกว้างขึ้นเมื่อต้องการตัวเลขเพิ่มเติม

มันไม่สวยเลยถ้าคุณต้องการจับภาพนี้ที่อื่น แต่เนื่องจากเป็นสิ่งที่ฉันไม่จำเป็นต้องทำ (ทุกอย่างถูกเขียนไปยังล็อกไฟล์แล้วฉันแค่อยากจะดูหลายรายการพร้อมกันแบบเรียลไทม์) ที่ดีที่สุด วิธีที่จะสูญเสียหมายเลขบรรทัดและมีเพียงคำนำหน้าของฉันคือการเริ่มต้น-sสายที่มีผลตอบแทนการขนส่ง (CR หรือ ^ M หรือ Ctrl-M) ตัวอย่างเช่น:

#!/bin/ksh

# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.

PGRP=$$

for LOGFILE in widget framas dweezil
do
(
    tail -f $LOGFILE 2>&1 |
    nl -s"^M${LOGFILE}>  "
) &
sleep 1
done

read KILLEM

kill -- -${PGRP}

1
ใช้-uตัวเลือกเพื่อ sed เพื่อหลีกเลี่ยงการบัฟเฟอร์
ไบรอัน Larsen

2
การปิดการบัฟเฟอร์สามารถปิดได้ด้วย unbuffer / stdbuf ดูunix.stackexchange.com/q/25372/6205
myroslav

2

ใช้ ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

ทดแทนนี้สำหรับแต่ละบรรทัด ( ,) จุดเริ่มต้นของบรรทัด ( ^) prefixด้วย wqบันทึกและออก

หากสตริงการแทนที่มีเครื่องหมายทับเราสามารถใช้ตัวคั่นอื่นsแทน:

ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE

ฉันยกเครื่องหมายตัวคั่น here-doc EOE("end of ed") เพื่อป้องกันการขยายพารามิเตอร์ ในตัวอย่างนี้มันจะทำงานอย่างไม่มีเงื่อนไขเช่นกัน แต่เป็นวิธีปฏิบัติที่ดีในการป้องกันความประหลาดใจหากคุณเคยมี$สคริปต์ ed ของคุณ


2

การใช้ & (ส่วนทั้งหมดของอินพุตที่ตรงกับรูปแบบ”):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

หรือใช้การอ้างอิงย้อนกลับ:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt

2
  1. นอกจากนี้คุณยังสามารถทำได้โดยใช้เทคนิคการย้อนกลับ

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. คุณสามารถใช้กับ awk แบบนี้ได้

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    

1

นี่คือตัวอย่างสรุปโดยใช้sedวิธีการจากคำตอบนี้ :

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

prefix_lines

function show_help()
{
  IT=$(CAT <<EOF
    Usage: PREFIX {FILE}

    e.g.

    cat /path/to/file | prefix_lines "WOW: "

      WOW: some text
      WOW: another line
      WOW: more text
  )
  echo "$IT"
  exit
}

# Require a prefix
if [ -z "$1" ]
then
  show_help
fi

# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
  # If no stdin exists
  if [ -t 0 ]; then
    show_help
  fi
  FILE=/dev/stdin
fi

# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE

2
สิ่งนี้จะใช้งานไม่ได้หากPREFIXมีอักขระพิเศษใด ๆ ที่น่าสนใจเหมือนสแลช
josch

จุดดี ... หากคุณพบว่าคุณใช้สแลชมากคุณสามารถใช้ตัวคั่นอื่นกับส่วนที่มีรายละเอียดตามที่นี่ซึ่งจะช่วยให้คุณสามารถใช้มันในการค้นหา ตัวอักษรพิเศษอื่น ๆ สามารถใส่เข้าไปได้โดยการใช้สแลชเช่นprefix_lines \*
Brad Parks

0

สำหรับคนที่ใช้ระบบ BSD / OSX มียูทิลิตี้ที่เรียกว่าlamสั้นสำหรับลามิเนต lam -s prefix fileจะทำในสิ่งที่คุณต้องการ ฉันใช้มันในท่อเช่น:

find -type f -exec lam -s "{}: " "{}" \; | fzf

... ซึ่งจะค้นหาไฟล์ทั้งหมด, exec lam ในแต่ละไฟล์, ให้แต่ละไฟล์นำหน้าชื่อไฟล์ของตัวเอง (และปั๊มผลลัพธ์ไปยัง fzf สำหรับการค้นหา)


คุณพูดถูกมันเป็นคำสั่ง BSD เท่านั้น POSIX แทนที่ด้วย paste แต่วางไม่ได้มีคุณสมบัติในการเพิ่มสตริงคั่นเต็ม ฉันจะอัปเดตคำตอบของฉัน
Ray
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.