แทรกบรรทัดที่หมายเลขบรรทัดเฉพาะด้วย sed หรือ awk


146

ฉันมีไฟล์สคริปต์ที่ฉันต้องแก้ไขด้วยสคริปต์อื่นเพื่อแทรกข้อความที่บรรทัดที่ 8

สตริงที่จะแทรก: ลงในไฟล์ที่เรียกว่าProject_Name=sowsteststart

ฉันพยายามใช้ awk และ sed แต่คำสั่งของฉันกำลังสับสน

คำตอบ:


231
sed -i '8i8 This is Line 8' FILE

เม็ดมีดที่บรรทัด 8

8 This is Line 8

เป็นไฟล์ FILE

-i ทำการแก้ไขโดยตรงไปยังไฟล์ FILE, ไม่มีเอาต์พุตไปยัง stdout, ดังที่ได้กล่าวไว้ในความคิดเห็นโดย glenn jackman


3
ใช่สวิตช์ -i นั้นเฉพาะสำหรับ GNU-sed
ผู้ใช้ที่ไม่รู้จัก

1
ไม่ได้ -i แปลว่า "แก้ไขไฟล์ที่ระบุ" การแทรกกับการผนวกจะทำได้ด้วย '8isomething' กับ '8asomething' ซึ่งเป็นอิสระจาก -i-switch
ผู้ใช้ไม่รู้จัก

11
ผู้ใช้ mac: กับ homebrew, brew install gnu-sedจากนั้นใช้กับgsed
cwd

4
มันมีประโยชน์มาก! มีให้ฉันแทรกช่องว่างที่จุดเริ่มต้นของบรรทัดหรือไม่ ฉันสังเกตเห็นว่า sed ไม่ได้สนใจที่ช่องว่างเริ่มต้น ...
elju

9
@elju: sed '8i\ 8 This is Line 8' FILEใช่หน้ากากด้วยเครื่องหมาย:
ผู้ใช้ไม่ทราบ

32

edคำตอบ

ed file << END
8i
Project_Name=sowstest
.
w
q
END

.บนบรรทัดของตัวเองสิ้นสุดโหมดอินพุต; wเขียน; qลาออก GNU ed มีwqคำสั่งให้บันทึกและออก แต่รุ่นเก่าไม่มี

อ่านเพิ่มเติม: https://gnu.org/software/ed/manual/ed_manual.html


19

OS X / macOS / FreeBSD sed

-iธงทำงานแตกต่างกันบน MacOS sedกว่าใน sedGNU

นี่คือวิธีใช้บน macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

ดูman 1 sedข้อมูลเพิ่มเติม


18

คำตอบที่ awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@glenn jackman ฉันต้องเข้าสู่#define SERVER@"http://10.35.42.54/ms0.8"บรรทัดที่ต้องการ ฉันจะบรรลุสิ่งนี้ได้อย่างไร
Nevin Raj Victor

1
ฉันคิดว่า Nevin ต้องหนีคำพูดในสตริงด้วยแบ็ก

@waLLe เริ่มต้นด้วยหน้าข้อมูล awkซึ่งมีคำอธิบายที่ดีว่า awk ทำงานอย่างไร ที่นี่ฉันมี 2 "เงื่อนไข {action}" คู่ที่ 2 ไม่มีเงื่อนไขซึ่งหมายความว่าการกระทำจะดำเนินการสำหรับทุกบันทึก หลังจากที่คุณอ่านจบแล้วและคุณยังมีคำถามอยู่ขอให้ฉันรู้
เกล็นแจ็คแมน

@glennjackman เกือบแล้ว .. ไม่ได้รับสิ่งนี้: file> file.new
w411 3

"file" หมายถึงชื่อของไฟล์ที่ awk ทำงานอยู่ >เป็นสัญลักษณ์การเปลี่ยนเส้นทางของเชลล์เพื่อให้เอาต์พุตของ awk ถูกเก็บไว้ในไฟล์ชื่อ "file.new"
เกล็นแจ็คแมน

16

POSIX sed(และเช่น OS X ของsedที่sedด้านล่าง) ต้องiจะตามมาด้วยเครื่องหมายและขึ้นบรรทัดใหม่ นอกจากนี้อย่างน้อย OS X sedจะไม่รวมบรรทัดใหม่หลังจากข้อความที่แทรก:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

ในการแทนที่บรรทัดคุณสามารถใช้คำสั่งc(เปลี่ยน) หรือs(แทนที่) ด้วยที่อยู่ตัวเลข:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

ทางเลือกโดยใช้awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkตีความแบ็กสแลชในตัวแปรที่ส่งผ่านด้วย-vแต่ไม่อยู่ในตัวแปรที่ส่งผ่านโดยใช้ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

ทั้งสองENVIRONและ-vถูกกำหนดโดย POSIX


7

โซลูชั่น Perl:

รวดเร็วและสกปรก:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l ตัดการขึ้นบรรทัดใหม่และเพิ่มกลับเข้ามาโดยไม่จำเป็นต้องมี "\ n"
  • -p วนซ้ำผ่านไฟล์อินพุตพิมพ์ทุกบรรทัด
  • -e รันรหัสในคำพูดเดียว

$. คือหมายเลขบรรทัด

เทียบเท่ากับโซลูชัน awk ของ @ glenn โดยใช้อาร์กิวเมนต์ที่มีชื่อ:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s เปิดใช้งานตัวแยกวิเคราะห์อาร์กิวเมนต์พื้นฐาน
  • -- ป้องกัน -n และ -s จากการแยกวิเคราะห์โดย parser อาร์กิวเมนต์ perl มาตรฐาน

อาร์กิวเมนต์คำสั่งตำแหน่ง:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

ตัวแปรสภาพแวดล้อม:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV เป็นแฮชซึ่งมีตัวแปรสภาพแวดล้อมทั้งหมด

Getopt เพื่อแยกอาร์กิวเมนต์ลงในแฮช% o:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: ชื่อตัวเลือกที่ยาวและยาวกว่า

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt เป็นโซลูชันไลบรารีมาตรฐานที่แนะนำ
สิ่งนี้อาจ overkill สำหรับสคริปต์ Perl แบบบรรทัดเดียว แต่สามารถทำได้


2
ขอชื่นชมคุณคริสที่สละเวลาอธิบายทุกอย่างและจัดวางอย่างดี แต่ว้าวนี่คือเหตุผลที่ฉันไม่ชอบ perl
rsaw

5

สำหรับผู้ที่อยู่บน SunOS ซึ่งไม่ใช่ GNU รหัสต่อไปนี้จะช่วย:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J ถูกแทรกด้วย ^ V + ^ J
  • เพิ่มบรรทัดใหม่หลังจาก '1i
  • \ ต้องเป็นอักขระตัวสุดท้ายของบรรทัด
  • ส่วนที่สองของคำสั่งจะต้องอยู่ในบรรทัดที่สอง

5

sed -e '8iProject_Name=sowstest' -i start ใช้ GNU sed

วิ่งตัวอย่าง:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 

ส่วนท้าย$มาจากที่ไหนในบรรทัดที่ 3 หลังจากการแทรก
jww

มันมาจาก-Aธงcat:)
jno

เกิดอะไรขึ้นถ้าสตริงที่คุณต้องการแทรกมีเครื่องหมายคำพูด, วงเล็บ ฯลฯ ?
Anentropic

ดูการอัปเดตข้อความด้านบน นั่นหมายความว่าคุณจะต้องหลบหนีตัวอักษรเหล่านั้นตามความเหมาะสม
jno

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