วิธีการเลือกการเกิดขึ้นครั้งแรกระหว่างสองรูปแบบรวมถึงพวกเขา


27

ฉันจะเลือกสิ่งที่เกิดขึ้นครั้งแรกระหว่างสองรูปแบบรวมถึงพวกเขา ควรใช้หรือsedawk

ฉันมี:

text
something P1 something
content1
content2
something P2 something
text
something P1 something
content3
content4
something P2 something
text

ฉันต้องการเกิดขึ้นครั้งแรกของเส้นระหว่าง P1 และ P2 (รวมถึงสาย P1 และสาย P2):

something P1 something
content1
content2
something P2 something

คำตอบ:


22
sed '/P1/,/P2/!d;/P2/q'

... จะทำงานได้อย่างมีประสิทธิภาพโดยการdลบทุกบรรทัดที่!ไม่อยู่ในช่วงจากนั้นquitting ในครั้งแรกที่พบจุดสิ้นสุดของช่วง มันไม่ได้ล้มเหลวสำหรับ P2 ก่อนหน้า P1 และไม่จำเป็นต้องใช้ไวยากรณ์เฉพาะของ GNU ในการเขียนเพียงอย่างเดียว


ยอดเยี่ยม ดีกว่าของฉันมาก
muru

1
@muru - มักจะง่ายกว่าที่จะหลีกเลี่ยงความขัดแย้งหากคุณพยายามกำหนดเป้าหมายของ autoprint - ปล่อยให้วงจรทำงานให้คุณ นั่นเป็นนิสัยที่ฉันตกหลุมอยู่แล้ว ฉันคิดว่ามันอาจจะอธิบายได้ดีที่สุดว่าเป็นลูกพรุนกับวิธีการเลือก - ฉันมักจะเลิกกับรูปแบบมากกว่าที่จะมองหามัน
mikeserv

สิ่งนี้จะหยุดทำงานเมื่อประมวลผลขนาดใหญ่ของไฟล์
Brain90

@ Brain90 - ไม่ควร หากคุณสามารถทำซ้ำการร้องเรียนของคุณได้อย่างน่าเชื่อถือคุณควรจัดการกับผู้ดูแลsed... นั่นเป็นข้อผิดพลาดในการsedทำงานของคุณและไม่ใช่สคริปต์ tbe ด้านบน
mikeserv

1
@mikeserv ฉันจะไม่พูดถ้าฉันไม่ได้ ความกังวลของคุณเกี่ยวกับว่าฉันสนใจตัวละครสองหรือสามตัวนั้นแปลกหรือไม่: ฉันสังเกตเห็นว่าการแสดงออกของ sed ทำงานได้ทั้งในและนอก/P2/qระบบ แค่นั้นแหละ. ฉันอยากรู้เกี่ยวกับบางสิ่งบางอย่างและต้องการแบ่งปันสิ่งที่ฉันพบ
Alexej Magura


8

ในsed:

sed -n '/P1/,/P2/p; /P2/q'
  • -nไม่แสดงการพิมพ์เริ่มต้นและคุณพิมพ์บรรทัดระหว่างช่วงที่อยู่ที่ตรงกันโดยใช้pคำสั่ง
  • โดยปกติจะเป็นการจับคู่ทั้งสองส่วนดังนั้นคุณจึงออก ( q) เมื่อการP2จับคู่ครั้งแรก

นี้จะล้มเหลวถ้ามาก่อนP2 P1หากต้องการจัดการกับกรณีดังกล่าวให้ลอง:

sed -n '/P1/,/P2/{p; /P2/q}'

1
ฉันไม่เห็นด้วย; คำตอบของ mikeserv ไม่ได้ดีไปกว่าของคุณ
G-Man กล่าวว่า 'Reinstate Monica'

@ g-man - pshaw แต่ฉันแค่คิดในสิ่งเดียวกัน
mikeserv

1
@gman - ไม่ ตอนนี้ฉันเข้าใจแล้ว วิธีเหมืองดีกว่า ไม่ {stack}!
mikeserv

1

หากคุณต้องการข้ามรูปแบบด้วยตัวเองนี่คือawkรุ่น:

awk '/P2/ {exit} /P1/ {f=1; next} f' file

ใช้งานได้สำหรับฉัน คุณสามารถเพิ่มข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของคำสั่งได้หรือไม่
0xAffe

1

awkวิธีแก้ปัญหาที่ง่ายกว่า(เรียงลำดับกึ่งกลางระหว่าง คำตอบของ iruvarและ  คำตอบของ muruแต่ไม่ใช่การใช้ตัวแปร):

awk '/P1/,/P2/ { print }  /P2/ { exit }'

และอย่างที่ muru สังเกตไว้ถ้า P2 แรกปรากฏขึ้นก่อน P1 แรกสิ่งนี้จะไม่พิมพ์อะไรเลย

แน่นอนถ้าคุณต้องการพิมพ์ช่วง P1-P2 ทั้งหมด:

something P1 something
content1
content2
something P2 something
something P1 something
content3
content4
something P2 something

เพิ่งออกจากexitส่วนที่:

awk '/P1/,/P2/ { print }'


0

หากต้องการข้ามรูปแบบด้วยตนเองและแสดงเฉพาะบล็อกแรกที่จับคู่ใน GNU ชุดเดียว:

sed -nre '/STARTPATTERN/ {:a;n;/ENDPATTERN/{b;};p;ba}' file
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.