วิธีอ่านบางบรรทัดหลังจากค้นหาข้อความ


12

ฉันจะอ่านจำนวนบรรทัดหลังจากค้นหาข้อความได้อย่างไร

เช่น.:

อ่าน 2 บรรทัดถัดไปหลังจากค้นหา "Unix" บน:

Test 1
Test 2
Test 3
Test 4
UNIX
Test 5
Test 6
Test 7
Test 8
Test 9

ผลลัพธ์สามารถ:

Test 5
Test 6

หมายเหตุ: "Unix" ในตัวอย่างที่ผ่านมาเป็นอาร์กิวเมนต์และมันอาจเป็นข้อความอื่น ๆ

สิ่งที่ฉันมี:

ฉันยังขาดความคิดต้องการแค่แสงสว่าง กำลังคิดที่จะสร้างสคริปต์อื่นขึ้นมาเพื่อทำสิ่งนั้น

คำตอบ:


10

awkวิธีการแก้ปัญหา:

$ awk '$0 == "UNIX" {i=1;next};i && i++ <= 2' file
Test 5
Test 6

คำอธิบาย

  • /^UNIX$/{i=1;next}: ถ้าเราเห็นUNIXเราตั้งค่าตัวแปรi = 1ประมวลผลเป็นอินพุตถัดไป

  • ถ้าตัวแปรiมีการตั้งค่า (ความหมายที่เราเห็นUNIX) i && i++ <= 2การประเมินผลเฉพาะกับมูลค่าที่แท้จริงในสองบรรทัดถัดไปหลังจากที่UNIXก่อให้เกิดการดำเนินการเริ่มต้นดำเนินการawkprint $0

  • ก่อนที่จะเห็นUNIX, iไม่ได้กำหนดไว้และเริ่มต้นที่บรรทัดที่ 3 หลังUNIX, iมีมากขึ้นมูลค่ากว่า 2 ซึ่งทำให้การแสดงออกของi && i++ <= 2การประเมินเพื่อเท็จก่อให้เกิดawkอะไรที่ต้องทำ


หลังจากทดสอบคุณวิธีการแก้ปัญหาฉันได้รับข้อความแสดงข้อผิดพลาดนี้: ข้อผิดพลาด systax near line 1 bailing out near line 1
Cold

@Cold: คุณทำงานอะไร โปรดทราบว่า$เครื่องหมายที่จุดเริ่มต้นของคำตอบของฉันคือ shell prompt ไม่ใช่ส่วนหนึ่งของawkคำสั่ง
cuonglm

ตัวแปรอื่น:awk '/^UNIX$/ {s=NR;next} s && NR<=s+2'
musiphil

ฉันรู้ว่า @cuonglm
เย็น

@Cold: OS ของคุณคืออะไร
cuonglm

12

grepวิธีการแก้ปัญหา:

grep -A2 -P '^UNIX$' file

คำอธิบาย: -Aหมายถึง: พิมพ์สองบรรทัดถัดไปหลังจากการแข่งขัน

หรือ awk:

awk '$0=="UNIX"{getline; print; getline; print}' file

คำอธิบาย:คำสั่งนั้นค้นหา UNIX ในบรรทัด ( $0=="UNIX") หากได้รับมันจะได้รับต่อไปในบัฟเฟอร์ ( getline) และพิมพ์บัฟเฟอร์ ( print) ทำสองครั้ง

หรือใช้sed:

sed -n '/^UNIX$/{n;p;n;p}' file

คำอธิบาย:สิ่งเหล่านี้ใช้สำหรับ UNIX ( /^UNIX$/) หากมีการพบว่ามัน txecutes {...}มีส่วนร่วมในการ nหมายถึงถัดไปpหมายถึงการพิมพ์ ทำเช่นนี้สองครั้ง


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

หากจำนวนบรรทัดเปลี่ยนแปลงจำนวนการเปลี่ยนแปลงที่ฉันจะทำได้ในสองตัวเลือกล่าสุดเป็นเท่าใด ขอบคุณ
เย็น

@Cold ดูการแก้ไขของฉัน หากต้องการเปลี่ยนจำนวนหากบรรทัดมีการทำซ้ำgetline; print;ส่วนในawkคำสั่งหรือn;p;ส่วนในsedคำสั่ง
ความโกลาหล

ขอบคุณ @chaos แต่ยิ่งมีจำนวนบรรทัดมากเท่าไหร่การแสดงออกที่เพิ่มขึ้นและการเปลี่ยนแปลงนั้นไม่สามารถทำได้ในความคิดของฉัน คุณไม่คิดว่า? ถ้า 100 บรรทัด?
เย็น

@Cold จากนั้นผมจะใช้วิธีการแก้ปัญหา grep grep -A100 -P '^UNIX$' file | tail -n +2ด้วย ส่วนท้ายคือการลบภาระแรก ในอื่น ๆ (sed, awk) คุณจะต้องเขียนลูปสิ่งที่ทำให้มันง่ายน้อยกว่า
ความโกลาหล

4
grep -A 2 UNIX file.txt

manpage ของ grep อธิบายถึงตัวเลือกดังนี้:

  -A NUM, --after-context=NUM
      Print NUM  lines  of  trailing  context  after  matching  lines.
      Places  a  line  containing  --  between  contiguous  groups  of
      matches.

สวัสดี @ ริ้วรอยคำตอบที่ดี แต่ grep ของฉันมีเพียงตัวเลือกนี้ "hblcnsviw" แต่ logics นั้นดี ขอบคุณ
เย็น

สิ่งนี้จะพิมพ์UNIXออกมาเช่นกัน
cuonglm

การละเว้นUNIXท่อไปยังtail: [...] | tail -n +1หรือ:sed [...] | sed '1d'
DopeGhoti

1
@DopeGhoti: tailและsed '1d'ข้อเสนอแนะของคุณทำงานอย่างถูกต้องเฉพาะในกรณีที่UNIXปรากฏเพียงครั้งเดียวในการป้อนข้อความ คำตอบอื่น ๆ ทั้งหมดอนุญาตให้เกิดขึ้นหลายครั้ง ... | grep -v UNIXมันอาจจะดีกว่าที่จะแนะนำ เป็นที่ยอมรับว่าจะเกิดความสับสนหากUNIXปรากฏในบรรทัดที่ 15 และ 17
G-Man กล่าวว่า 'Reinstate Monica'

จุดที่ดี ฉันค่อนข้างแน่ใจว่ามันสามารถทำได้sedด้วยรูปแบบบางอย่างsed '/UNIX/d;n;n;p/' /path/to/fileซึ่งฉันเพิ่ง sussed และส่งเป็นคำตอบ
DopeGhoti

0

ดูเหมือนว่าจะทำเคล็ดลับอย่าง:

sed -n '/UNIX/{n;p;n;p}' /path/to/file

พิสูจน์แนวคิด:

$ for i in {1..9}; do echo $i; done | sed -n '/4/{n;p;n;p}'
5
6

1
forไม่จำเป็นต้องใช้เปลือกย่อยรอบวงของคุณ
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

แน่นอนมันไม่ได้; มันเป็นเศษเล็กเศษน้อยของ faffery อื่น ๆ ที่ฉันอยู่ท่ามกลางเปลือกหอยก่อนหน้านี้ในวันนั้น ลบ Parens แล้ว
DopeGhoti

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