ลบหมายเลขบรรทัดเฉพาะจากไฟล์ข้อความโดยใช้ sed?


235

ฉันต้องการลบหมายเลขบรรทัดอย่างน้อยหนึ่งหมายเลขออกจากไฟล์ ฉันจะทำสิ่งนี้โดยใช้ sed ได้อย่างไร


1
คุณสามารถยกตัวอย่างที่เจาะจงมากขึ้นเกี่ยวกับสิ่งที่คุณต้องการได้หรือไม่? คุณจะตัดสินใจเลือกบรรทัดที่จะลบอย่างไร
Mark Byers

อาจดูได้ที่stackoverflow.com/questions/13272717/…และใช้การย้อนกลับ (พิมพ์ถ้าคีย์ไม่ได้อยู่ในอาร์เรย์ที่เชื่อมโยง)
tripleee

คำตอบ:


374

หากคุณต้องการลบบรรทัดที่ 5 ถึง 10 และ 12:

sed -e '5,10d;12d' file

นี่จะพิมพ์ผลลัพธ์ไปที่หน้าจอ หากคุณต้องการบันทึกผลลัพธ์ไปยังไฟล์เดียวกัน:

sed -i.bak -e '5,10d;12d' file

จะเป็นการสำรองไฟล์สูงสุดfile.bakและลบบรรทัดที่กำหนด

หมายเหตุ: หมายเลขบรรทัดเริ่มต้นที่ 1 บรรทัดแรกของไฟล์คือ 1 ไม่ใช่ 0


32
ไม่ใช่ยูนิกซ์ทั้งหมดที่มี gnu sed ด้วย "-i" อย่าทำผิดพลาดในการย้อนกลับไปที่ "sed cmd file> file" ซึ่งจะลบไฟล์ของคุณ
สรรเสริญ

4
เกิดอะไรขึ้นถ้าฉันต้องการลบบรรทัดที่ 5 จนถึงบรรทัดสุดท้าย
Jürgen Paul

14
@WearetheWorldsed -e '5,$d' file
Brian Campbell

1
@BrianCampbell ฉันควรทำอย่างไรเพื่อลบเฉพาะบางบรรทัด?
Kanagavelu Sugumar

14
sed -e '5d' file@KanagaveluSugumar ไวยากรณ์คือ<address><command>; โดยที่<address>สามารถเป็นได้ทั้งบรรทัดเดียว5หรือช่วงของบรรทัดที่ชอบ5,10และคำสั่งdจะลบบรรทัดหรือบรรทัดที่กำหนด ที่อยู่อาจเป็นนิพจน์ทั่วไปหรือเครื่องหมายดอลลาร์ที่$ระบุบรรทัดสุดท้ายของไฟล์
Brian Campbell

50

คุณสามารถลบบรรทัดเดียวที่มีหมายเลขบรรทัดโดย

sed -i '33d' file

การดำเนินการนี้จะลบบรรทัดที่หมายเลข 33 บรรทัดและบันทึกไฟล์ที่อัพเดต


1
ในกรณีของฉัน "sed" ลบบรรทัดผิด sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'ดังนั้นผมจึงใช้วิธีการนี้: ขอบคุณ!
Eduardo Lucio

เช่นเดียวกันที่นี่ฉันเขียนลูปและไฟล์บางไฟล์หายไปอย่างถูกต้อง แต่บางไฟล์ก็หายไปอีกหนึ่งบรรทัดเช่นกันไม่มีเงื่อนงำว่าเกิดอะไรขึ้น (GNU / Linux bash4.2) คำสั่ง awk ทำงานได้ดีในลูป
FatihSarigol

ระวังการใช้ sort -r จริงๆถ้าคุณลบจากรายการของบรรทัดมิฉะนั้น sed แรกของคุณจะเปลี่ยนหมายเลขบรรทัดของทุกอย่างอื่น ...
Konchog

หากต้องการแสดงความคิดเห็นเกี่ยวกับการลบบรรทัดที่ไม่ถูกต้องภายในลูป: อย่าลืมเริ่มต้นด้วยหมายเลขบรรทัดที่ใหญ่ที่สุดมิฉะนั้นแต่ละบรรทัดที่ถูกลบจะชดเชยออฟไลน์หมายเลข…
Skippy le Grand Gourou

25

และ awk เช่นกัน

awk 'NR!~/^(5|10|25)$/' file

2
NB: บรรทัด awk นั้นทำงานได้อย่างน่าเชื่อถือสำหรับฉันมากกว่ารุ่น sed (ระหว่าง OS-X และ Ubuntu Linux)
Jay Taylor

3
โปรดทราบว่านี่จะไม่ลบอะไรในไฟล์ มันพิมพ์ไฟล์โดยไม่มีบรรทัดเหล่านี้ไปยัง stdout ดังนั้นคุณต้องเปลี่ยนเส้นทางผลลัพธ์ไปยังไฟล์ชั่วคราวแล้วย้ายไฟล์ชั่วคราวเพื่อแทนที่ต้นฉบับ
mivk


6

นี่เป็นอาการของ Antipattern เครื่องมือที่สร้างหมายเลขบรรทัดอาจถูกแทนที่ด้วยอันที่ลบบรรทัดทันที ตัวอย่างเช่น;

grep -nh error logfile | cut -d: -f1 | deletelines logfile

( deletelinesยูทิลิตี้ที่คุณต้องการจินตนาการ) อยู่ที่ไหนเหมือนกัน

grep -v error logfile

ต้องบอกว่าถ้าคุณอยู่ในสถานการณ์ที่คุณต้องการทำงานนี้จริงๆคุณสามารถสร้างsedสคริปต์อย่างง่ายจากไฟล์หมายเลขบรรทัด ตลก ( แต่บางทีอาจจะทำให้เกิดความสับสนเล็กน้อย) sedคุณสามารถทำเช่นนี้กับ

sed 's%$%d%' linenumbers

สิ่งนี้ยอมรับไฟล์หมายเลขบรรทัดหนึ่งรายการต่อบรรทัดและสร้างหมายเลขบรรทัดเดียวกันที่dต่อท้ายแต่ละบรรทัด นี่เป็นsedสคริปต์ที่ถูกต้องซึ่งเราสามารถบันทึกลงในไฟล์หรือ (ในบางแพลตฟอร์ม) ไพพ์ไปยังsedอินสแตนซ์อื่น:

sed 's%$%d%' linenumbers | sed -f - logfile

ในบางแพลตฟอร์มsed -fไม่เข้าใจอาร์กิวเมนต์ตัวเลือก-ให้หมายถึงอินพุตมาตรฐานดังนั้นคุณต้องเปลี่ยนเส้นทางสคริปต์ไปยังไฟล์ชั่วคราวและล้างมันเมื่อเสร็จแล้วหรืออาจแทนที่ lone dash ด้วย/dev/stdinหรือ/proc/$pid/fd/1ถ้าระบบปฏิบัติการของคุณ (หรือเชลล์ ) มีสิ่งนั้น

เช่นเคยคุณสามารถเพิ่ม-iก่อน-fตัวเลือกเพื่อให้sedแก้ไขไฟล์เป้าหมายแทนการสร้างผลลัพธ์ในเอาต์พุตมาตรฐาน บนแพลตฟอร์ม * BSDish (รวมถึง OSX) คุณต้องระบุอาร์กิวเมนต์ที่ชัดเจน-iเช่นกัน สำนวนที่พบบ่อยคือการให้อาร์กิวเมนต์ที่ว่างเปล่า; -i ''.


ฉันไม่ค่อยเห็นด้วยกับ "อาการของ antipattern" ประเภทไฟล์ที่มาร์กอัป (เช่น XML หรือ JSON) ต้องการบรรทัดที่เฉพาะเจาะจงที่ส่วนท้ายเพื่อให้เป็นไฟล์ที่ถูกต้อง ในกรณีนั้นมักเป็นวิธีที่เหมาะสมที่สุดในการลบบรรทัดเหล่านั้นใส่ลงในไฟล์ที่คุณต้องการเพิ่มจากนั้นเพิ่มบรรทัดเหล่านั้นอีกครั้งเนื่องจากการวางบรรทัดในระหว่างที่อยู่ห่างออกไปอาจเป็นความพยายามมากกว่าเดิม ความปรารถนาที่อาจเกิดขึ้นเพื่อหลีกเลี่ยงเครื่องมือพิเศษอย่างเซดเท่าที่คุณสามารถ
Egor Hans

ฉันไม่เข้าใจว่าคุณกำลังจินตนาการอะไร มีเป็นสถานการณ์ที่นี้เป็นวิธีการที่ถูกต้องตามกฎหมาย แต่ส่วนใหญ่ของกรณีที่ฉันได้เห็นมือใหม่ที่ทำมากหรือน้อยสิ่งที่ตัวอย่างแรกของฉันแสดงให้เห็นถึงกำลัง (บางทีพวกเขาอาจมาจากภาษาระดับต่ำจริงๆและใช้เพื่อแบ่งปัญหาของพวกเขาผ่านระดับโมเลกุลเพราะคุณต้องเป็น asm หรือ C)
Tripleee

การลบสิ่งจากจำนวนบรรทัดจาก XML หรือ JSON เสียงextermelyเปราะถ้าไม่เป็นอันตรายทันที
tripleee

สิ่งที่ฉันหมายถึงโดยทั่วไปคือในฐานะผู้สร้างไฟล์ดังกล่าวคุณรู้ว่าต้องทำอะไรที่ส่วนท้ายของเอกสาร (เช่นชุดวงเล็บปิด / วงเล็บเหลี่ยมในไม่กี่บรรทัดสุดท้ายของ JSON หรือแน่นอน แท็กปิดสำหรับ XML) ตระหนักถึงวิธีการที่ง่ายที่สุดในการขยายเอกสารดังกล่าวคือ 1) ลบไม่กี่บรรทัดที่ผ่านมา 2) เพิ่มเนื้อหาใหม่ 3) เพิ่มอีกสองสามบรรทัดสุดท้าย วิธีนี้เอกสารสามารถใช้ได้ทั้งก่อนและหลังการขยายโดยไม่จำเป็นต้องหาวิธีเพิ่มบรรทัดกลางเอกสาร
Egor Hans

1
จนถึงตอนนี้เป็นคำตอบเดียวที่มีทางออกที่เหมาะสมสำหรับบรรทัดจำนวนมาก (เช่นมีให้โดยไฟล์) และคำปรารภก็สมเหตุสมผลเช่นกัน มันสมควรได้รับการโหวตมากขึ้น BTW หากคุณต้องการพิมพ์บรรทัดแทนที่จะลบออกให้ใช้pแทนdพร้อมกับตัวเลือก-n(มันจะไม่ทำงานหากไม่มี-nและ!dจะไม่ทำงานเช่นกัน)
Skippy le Grand Gourou

2

ฉันต้องการเสนอข้อสรุปทั่วไปด้วย awk

เมื่อไฟล์ถูกสร้างโดยบล็อกที่มีขนาดคงที่และบรรทัดที่จะลบถูกทำซ้ำสำหรับแต่ละบล็อก awk สามารถทำงานได้ดีในลักษณะดังกล่าว

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  $0}'
 OriginFile.dat > MyOutputCuttedFile.dat

ในตัวอย่างนี้ขนาดของบล็อกคือ 2000 และฉันต้องการพิมพ์บรรทัด [1..713] และ [1026..1029]

  • NR เป็นตัวแปรที่ awk ใช้เพื่อจัดเก็บหมายเลขบรรทัดปัจจุบัน
  • % ให้ส่วนที่เหลือ (หรือโมดูลัส) ของการหารจำนวนเต็มสองจำนวน
  • nl=((NR-1)%BLOCKSIZE)+1ที่นี่เราเขียนในตัวแปรnlหมายเลขบรรทัดภายในบล็อกปัจจุบัน (ดูด้านล่าง)
  • ||และ&&มีผู้ประกอบการตรรกะหรือและและ
  • print $0 เขียนเต็มบรรทัด

Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
  +1   We add again 1 because we want to restore the desired order.

+-----+------+----------+------------+
| NR  | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
|  1  |  1   |    0     |     1      |
|  2  |  2   |    1     |     2      |
|  3  |  0   |    2     |     3      |
|  4  |  1   |    0     |     1      |
+-----+------+----------+------------+


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