ใน Bash ฉันจะเพิ่มสตริงหลังจากแต่ละบรรทัดในไฟล์ได้อย่างไร


112

ฉันจะเพิ่มสตริงหลังจากแต่ละบรรทัดในไฟล์โดยใช้ bash ได้อย่างไร สามารถทำได้โดยใช้คำสั่ง sed ถ้าเป็นอย่างไร

คำตอบ:


188

หากคุณsedอนุญาตให้แก้ไขผ่าน-iพารามิเตอร์:

sed -e 's/$/string after each line/' -i filename

ถ้าไม่คุณต้องสร้างไฟล์ชั่วคราว:

typeset TMP_FILE=$( mktemp )

touch "${TMP_FILE}"
cp -p filename "${TMP_FILE}"
sed -e 's/$/string after each line/' "${TMP_FILE}" > filename

ทำไมคุณtouchถึงไฟล์ชั่วคราว? และฉันจะทำให้sedคำสั่งมีเงื่อนไขเกี่ยวกับความสำเร็จของcpหรือต้นฉบับอาจสูญหายไป
หยุดชั่วคราวจนกว่าจะมีประกาศอีกครั้ง

ฉันแตะไฟล์เพื่อจองชื่อชั่วคราวอย่างรวดเร็ว สิ่งนี้อาจไม่จำเป็น ฉันคิดว่าคุณพูดถูกเกี่ยวกับการกำหนดเงื่อนไขคำสั่ง sed ต่อความสำเร็จของ cp ทำไมไม่แก้ไขโค้ดเพื่อทำการแก้ไข ฉันจะไม่รังเกียจเลยสักนิด! ขอแสดงความนับถือ Tom
Tom DeGisi

แล้วการเพิ่มสตริงก่อนบรรทัดล่ะ?
Oxwivi

10
@Oxwivi: sed -e 's/^/string after each line/' -i filename $ หมายถึง end-of-line ^ หมายถึงจุดเริ่มต้นของบรรทัด
Tom DeGisi

ถ้าฉันวางสายเข้าไปใน sed sed 's/^/string after each line/'จะทำในสิ่งที่ฉันคาดหวัง (ล่วงหน้าไปยังแต่ละบรรทัด) แต่sed 's/^/string after each line/'ไม่ทำ (มันจะแทนที่ทั้งบรรทัดด้วยสตริงต่อท้ายของฉัน) สิ่งที่ช่วยให้? ความคิดใด ๆ @TomDeGisi?
ฟิลาดัมส์

17

ฉันชอบใช้awk. หากมีเพียงคอลัมน์เดียวให้ใช้$0หรือแทนที่ด้วยคอลัมน์สุดท้าย

ทางเดียว,

awk '{print $0, "string to append after each line"}' file > new_file

หรือนี่

awk '$0=$0"string to append after each line"' file > new_file

1
นอกจากนี้ในการต่อท้ายหมายเลขบรรทัด (เช่นเดียวกับในกรณีของฉัน) เราสามารถใช้NRตัวแปรได้:awk '{print $0, NR}'
andrybak

2
@optimus ฉันได้ลองใช้วิธีของคุณแล้ว แต่ได้รับช่องว่างเพิ่มเติม BW พวกเขามีความคิดอย่างไรในการลบ
Adil Saju

@AdilSaju sed 's/ //g'สิ่งนี้ใช้ได้กับความต้องการของฉัน แต่จะลบช่องว่างในทุกบรรทัดนั่นคือตัวเลือกgสำหรับและทุกที่ในบรรทัด
Eklavyaa

@AdilSaju กรุณาเพิ่มรายละเอียด ถามคำถามใหม่ดีกว่า
Optimus Prime

@AdilSaju awk ลบเช่น, {print $0"string to append after each line"}
Culip


4
  1. เปลือก POSIXบริสุทธิ์และsponge:

    suffix=foobar
    while read l ; do printf '%s\n' "$l" "${suffix}" ; done < file | 
    sponge file
  2. xargsและprintf:

    suffix=foobar
    xargs -L 1 printf "%s${suffix}\n" < file | sponge file
  3. ใช้join:

    suffix=foobar
    join file file -e "${suffix}" -o 1.1,2.99999 | sponge file
  4. เครื่องมือเชลล์ใช้paste, yes, head & wc:

    suffix=foobar
    paste file <(yes "${suffix}" | head -$(wc -l < file) ) | sponge file

    หมายเหตุที่pasteแทรกแท็บ$suffixถ่านก่อน

แน่นอนว่าspongeสามารถแทนที่ด้วยไฟล์ temp ได้หลังจากนั้นก็แทนที่mvชื่อไฟล์เดิมเช่นเดียวกับคำตอบอื่น ๆ ...


1
สิ่งเหล่านี้ไม่เป็นที่ต้องการsedเว้นแต่ทรัพยากรจะมี จำกัด มาก
agc

ฉันชอบวิธีการแก้ปัญหาที่ไม่ใจเย็น sedไม่จำเป็นสำหรับงานง่ายๆเช่นนี้
Bruce


-9

Sed นั้นน่าเกลียดเล็กน้อยคุณสามารถทำได้อย่างหรูหราเช่นนี้:

hendry@i7 tmp$ cat foo 
bar
candy
car
hendry@i7 tmp$ for i in `cat foo`; do echo ${i}bar; done
barbar
candybar
carbar

2
ล้มเหลวสำหรับไฟล์ที่มีบรรทัดมากกว่าขีด จำกัด อาร์กิวเมนต์สูงสุดของเชลล์ ลอง: cat foo | ในขณะที่อ่าน; ทำ echo $ {a} bar; ทำหรืออะไรทำนองนั้นแทน; เป็นการทดแทนที่เหมาะสมสำหรับในกรณีส่วนใหญ่
alex

1
นอกจากนี้ยังล้มเหลวสำหรับบรรทัดที่มีช่องว่าง
หยุดชั่วคราวจนกว่าจะมีประกาศอีกครั้ง

1
เอ่อไม่มันไม่ล้มเหลวเดนนิส ขีด จำกัด อาร์กิวเมนต์สูงสุดของเชลล์? คริคกี้คุณกำลังคลั่งไคล้
hendry

ใช่มัน: $ cat foo foo bar baz alex @ armitage: ~ $ for i in cat foo; ทำ echo $ {i} bar; ทำ foobar barbar bazbar แต่หลังจากการทดสอบบางอย่างฉันอาจจะคิดผิดเกี่ยวกับเหตุผลของฉัน แต่เดนนิสพูดถูก
อเล็กซ์

3
@hendry ใช่สิ่งนี้จะล้มเหลวสำหรับบรรทัดที่มีช่องว่างเช่นecho "foo bar" | (for i in `cat`; do echo ${i}bar; done)ซึ่งพิมพ์ 2 บรรทัดแม้ว่าอินพุตจะเป็น 1 บรรทัดfoo bar(และcatการอ่านจาก stdin แทนที่จะเป็นไฟล์ก็ไม่ทำให้เกิดความแตกต่าง)
hyde
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.