พิมพ์การจับคู่บรรทัดและบรรทัดที่ n จากบรรทัดที่จับคู่


18

ฉันพยายามพิมพ์บรรทัดที่จับคู่และบรรทัดที่ 4 จากบรรทัดที่จับคู่ (บรรทัดที่มีนิพจน์ที่ฉันค้นหา)

ฉันใช้รหัสต่อไปนี้: sed -n 's/^[ \t]*//; /img class=\"devil_icon/,4p' input.txt

แต่จะพิมพ์เฉพาะเส้นที่ตรงกันเท่านั้น

นี่พิมพ์เฉพาะบรรทัดที่ 4 awk 'c&&!--c;/img class=\"devil_icon/{c=4}' input.txt

ฉันต้องการพิมพ์ทั้งคู่ที่จับคู่และบรรทัดที่ 4 เท่านั้น


ใช้ egrep "pattern" -A4
Valentin Bajrami

@ val0x00ff ที่พิมพ์เส้นในระหว่างเกินไป .. ที่อยู่: จะพิมพ์ต่อไป 4 สายที่เริ่มต้นจากเส้นจับคู่
Debal

คุณกำลังพูดว่า "ฉันกำลังพยายามพิมพ์บรรทัดที่จับคู่และบรรทัดที่ 4 จากบรรทัดที่ตรงกัน" สิ่งนี้grep -A 4 "pattern" file | sed -n '4p'ทำในสิ่งที่คุณต้องการอย่างแน่นอนเว้นแต่ว่าฉันเข้าใจผิดคุณ
Valentin Bajrami

ไม่มันไม่ การส่งออกของโค้ดข้างต้นเป็น</td>ซึ่งไม่ได้เป็นเส้นที่ 4
Debal

คำตอบ:


18

ใน awk คุณต้องทำดังนี้

awk '/pattern/{nr[NR]; nr[NR+4]}; NR in nr' file > new_file`

หรือ

awk '/pattern/{print; nr[NR+4]; next}; NR in nr' file > new_file`

คำอธิบาย

patternวิธีการแก้ปัญหาครั้งแรกที่พบว่าทุกสายที่แข่งขัน เมื่อพบการแข่งขันจะเก็บบันทึกหมายเลข ( NR) nrในอาร์เรย์ นอกจากนี้ยังเก็บระเบียนที่ 4 จากNRในอาร์เรย์เดียวกัน nr[NR+4]นี้จะกระทำโดย ทุกเรคคอร์ด ( NR) จะถูกตรวจสอบเพื่อดูว่ามีอยู่ในnrอาเรย์หรือไม่หากมีการพิมพ์เรคคอร์ด

วิธีที่สองนั้นใช้งานได้เหมือนกันยกเว้นเมื่อพบpatternว่ามันพิมพ์บรรทัดนั้นแล้วเก็บระเบียนที่ 4 ไว้ข้างหน้าในอาร์เรย์nrจากนั้นไปที่ระเบียนถัดไป จากนั้นเมื่อawkพบบันทึกที่ 4 นี้NR in nrบล็อกจะถูกดำเนินการและพิมพ์ระเบียน +4 ที่นั่นหลังจาก

ตัวอย่าง

sample.txtนี่คือแฟ้มข้อมูลตัวอย่างเช่น

$ cat sample.txt 
1
2
3
4 blah
5
6
7
8
9
10 blah
11
12
13
14
15
16

ใช้วิธีที่ 1:

$ awk '/blah/{nr[NR]; nr[NR+4]}; NR in nr' sample.txt 
4 blah
8
10 blah
14

ใช้วิธีที่ 2:

$ awk '/blah/{print; nr[NR+4]; next}; NR in nr' sample.txt 
4 blah
8
10 blah
14

3
ดี +1 คุณใช้awkทางลัดมากมายที่นี่คุณสามารถเพิ่มคำอธิบายสั้น ๆ (สิ่งต่าง ๆ เช่นการพิมพ์โดยนัยใน awk และอาร์เรย์นั้นเป็นแบบเชื่อมโยงเป็นต้น)
terdon

เห็นด้วยกับ @terdon กรุณาช่วยอธิบายโค้ดหน่อยได้ไหม
debal

@slm ขอบคุณสำหรับการปรับปรุงและให้คำตอบที่สมบูรณ์!
Valentin Bajrami

1
ขอบคุณสำหรับคำตอบฉันได้เรียนรู้สิ่งใหม่ ๆ ด้วยเช่นกัน
slm

4
sed -n 's/^[ \t]*/; /img class=\"devil_icon/,+4 { 3,5d ; p }' input.txt

{ 3,5d ; p }ฉันเพียงแค่เพิ่มการลบเส้นที่เหมาะสมก่อนที่จะพิมพ์


การแสดงออกของคุณสร้างข้อผิดพลาด: sed: -e expression #1, char 18: unknown option to s'`
แร่ธาตุ

4

คุณสามารถลองใช้-Aตัวเลือกด้วยgrepซึ่งจะระบุจำนวนบรรทัดหลังจากบรรทัดที่ตรงกันที่ควรพิมพ์ จับคู่สิ่งนี้ด้วยsedและคุณจะได้เส้นที่ต้องการ

grep -A 4 pattern input.txt | sed -e '2,4d'

ใช้sedเราลบจากบรรทัดที่สองจนถึงสี่


3
นี่ถือว่าเป็นการจับคู่ครั้งเดียวpatternในไฟล์
terdon

2

นี่คือวิธีใน Perl ซึ่งสามารถจัดการกับจำนวนบรรทัดที่ตรงกันโดยพลการ:

perl -ne '/pattern/ && do{$c=$.; print}; $.==$c+4 && print' file > new_file`

ในภาษา Perl ตัวแปรพิเศษ$.คือหมายเลขบรรทัดปัจจุบัน ดังนั้นทุกครั้งที่ผมพบว่าการจับคู่บรรทัดผมพิมพ์และบันทึกหมายเลขบรรทัดในฐานะที่เป็นpattern $cฉันจะพิมพ์อีกครั้งเมื่อหมายเลขบรรทัดปัจจุบันคือ 4 มากกว่าหมายเลขที่พิมพ์ก่อนหน้านี้


0
awk 'c&&!--c;/img class=\"devil_icon/{c=4};/img class=\"devil_icon/' input.txt

คุณกำลังค้นหาและแทนที่ คุณสามารถเพิ่มการค้นหาลงในคำสั่งเดียวกันและมันจะพิมพ์ทั้งสองอย่าง :)

awk 'c&&!--c;/pattern/{c=4};/pattern/' input.txt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.