แสดงไฟล์ทั้งหมดจนถึงการแข่งขัน


71

grep --before-context 5 แสดง 5 บรรทัดก่อนการแข่งขัน

ฉันต้องการแสดงทุกอย่างก่อนการแข่งขัน
การgrep --before-context 99999999ทำงานจะได้ผล แต่มันไม่ได้เป็นมืออาชีพมากนัก

วิธีการแสดงไฟล์ทั้งหมดถึงการแข่งขัน?

คำตอบ:


95

Sedดีกว่าสำหรับเรื่องนั้น

แค่ทำ:

sed '/PATTERN/q' FILE

มันได้ผลเช่นนี้:

สำหรับแต่ละบรรทัดเราจะดูว่าตรงกันหรือไม่/PATTERN:

  • ถ้าใช่เราพิมพ์และออกจาก
  • มิฉะนั้นเราจะพิมพ์

นี้เป็นทางออกที่มีประสิทธิภาพมากที่สุดเพราะทันทีที่เห็นPATTERNก็หยุดทำงาน หากไม่มีqsed จะอ่านไฟล์ที่เหลือต่อไปและไม่ทำอะไรกับมันเลย สำหรับไฟล์ขนาดใหญ่มันสามารถสร้างความแตกต่าง

เคล็ดลับนี้ยังสามารถใช้เพื่อเลียนแบบhead:

sed 10q FILE

ลองแล้วมันจะออกบรรทัดแรกของไฟล์ ... แม้ว่าการจับคู่จะอยู่ที่บรรทัดที่ 38
Nicolas Raoul

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

ฉันได้ลองใช้คำสั่งของคุณก่อนที่คุณจะแก้ไขมันคือ: sed '/ PATTERN / p; q' FILE
Nicolas Raoul

7
ฉันควรทำอย่างไรถ้าฉันไม่ต้องการพิมพ์บรรทัดที่มีรูปแบบตรงกัน
tommy.carstensen

4
@ tommy.carstensen: sed '/PATTERN/Q' FILEจะข้ามบรรทัดที่ตรงกัน Qเป็นส่วนขยายของ GNU ดังนั้นจึงไม่สามารถทำงานกับ sed ใด ๆ
อเล็กซ์ O

37

sed สามารถแทนที่ฟังก์ชั่นส่วนใหญ่ของ grep ได้

sed -n '1,/<pattern>/ p' <file>

นี่หมายถึงการพิมพ์จากบรรทัดแรกจนกระทั่งรูปแบบตรงกัน

ตัวอย่างของช่วงที่สอง

sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2

3
คำสั่งนี้ดี แต่คุณทำได้ดีกว่า วิธีนี้จะอ่านไฟล์ทั้งหมด แต่ก็เป็นไปได้ที่จะออกจากทันทีที่พบการแข่งขัน
มิเคล

3
ฉันควรทำอย่างไรถ้าฉันไม่ต้องการพิมพ์บรรทัดที่มีรูปแบบตรงกัน
tommy.carstensen

34

พิมพ์ได้ถึงและรวมถึงการแข่งขัน:

awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename

พิมพ์ได้สูงสุด แต่ไม่รวมการจับคู่:

awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename

11
Qเจ๋ง แต่ gnu เฉพาะ afaik sed -n '/pattern/!p;//q'จะพกพาได้มากกว่านี้
don_crissti

@don_crissti: คุณควรให้คำตอบฉันคิดว่ามันเป็นสิ่งที่ดี (: ฉันสงสัยเล็กน้อยว่ามันทำงานอย่างไรฉันเชื่อว่า!ทำให้pใช้กับบรรทัดที่ไม่ตรงกันpatternแต่แล้ว//qฉันสับสน ...
jwd

2
@don_crissti: อ่าฉันเข้าใจแล้ว - //หมายถึง "นิพจน์ปกติก่อนหน้า" (ฉันคิดว่ามันหมายถึง "จับคู่สตริงว่าง") ผมคิดว่ารุ่นสั้นของการแก้ปัญหาเดียวกันคือsed -n '/pattern/q;p?
jwd

@jwd - แน่นอนว่ามันสั้นกว่า 👍
don_crissti

1

grepวิธีGNU ล้วนๆดังต่อไปนี้ไม่มีประสิทธิภาพ

ค้นหาทุกอย่างจนถึงอินสแตนซ์แรกของสตริง " foo " ในแถบไฟล์โดยใช้สามgreps:

grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar

จับคู่กับอินสแตนซ์สุดท้ายของ " foo ":

grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar

หมายเหตุ: รายละเอียดในวันสุดท้ายที่grepสามารถพบได้ใน: Regex (grep) สำหรับการค้นหาหลายสายที่จำเป็น


ทำไมคนเราถึงอยากใช้ 7 grepวินาที (+ pcre) เมื่อเป็นเรื่องของการเรียกใช้เพียงครั้งเดียวsed: sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'??
don_crissti

@don_crissti sedดูเหมือนว่ารหัสของคุณจะคุ้มค่ากับคำตอบของตัวเองหรือสามารถเพิ่มลงในรายการอื่น Re 7 greps: เนื่องจากไม่มีgrepคำตอบ ... (บวกคำตอบช่วยแสดงว่าทำไมถึงไม่)
agc

ไม่ใช่รหัสของฉันเพียงคลิกที่มัน ... แม้ว่าจะเป็นรหัสของฉันมันก็ไม่ตอบคำถาม Q ที่นี่ดังนั้นฉันจะไม่โพสต์มันเป็นคำตอบ
don_crissti

1

กำลังเพิ่มลงในคำตอบของ Mikel ด้านบน ...


หากต้องการพิมพ์บรรทัดทั้งหมดจนถึง แต่ไม่รวมบรรทัดแรกในFILEที่มีPATTERNให้ลอง:

  • sed '/.*PATTERN.*/{s///;q;}' FILE

สิ่งนี้ตรงกับทั้งบรรทัดที่มีรูปแบบแทนที่ด้วยบรรทัดว่างจากนั้นออกโดยไม่ต้องดำเนินการกับไฟล์ที่เหลือ


โพสต์สคริปต์:

วิธีที่ง่ายที่สุด / ชัดเจนที่สุดที่ฉันสามารถคิดได้เพื่อป้องกันการพิมพ์บรรทัดใหม่พิเศษในตอนท้าย (โดยไม่เกี่ยวข้องกับเครื่องมืออื่น) คือการทำงานอีกครั้งและลบบรรทัดสุดท้ายใหม่:

sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'

... และเนื่องจากตอนนี้เรากำลังลบบรรทัดนั้นอยู่ผลงานก่อนหน้าของเราซ้ำซ้อนและเราสามารถทำให้:

sed '/PATTERN/q' FILE | sed '$d'

คำตอบของ Glenn - และความคิดเห็นของฉันที่นั่น - แสดงวิธีดำเนินการด้วยการsedเรียกใช้เพียงครั้งเดียว
don_crissti

(ขอบคุณสำหรับสิ่งนั้น - ฉันเห็นความคิดเห็นของคุณเกี่ยวกับคำตอบของ agc แต่ไม่ได้รับอย่างใดอย่างหนึ่งหรือเพียงแค่อ่านเพราะสมองของฉันไม่ชอบเนกาทีฟสองเท่า) เนื่องจากฉันใช้สิ่งนี้ทั้งในนามแฝงtcshและbashนามแฝงฉันต้องแน่ใจว่าฉัน มีโซลูชันบรรทัดเดียวที่ค่อนข้างกระชับซึ่งทำงานได้ทั้งแบบมาตรฐานและ GNU sed(สำหรับการพกพา); ข้อกำหนดทั้งหมดที่การบริจาคของคุณอาจปฏิบัติตามได้เป็นอย่างดี ในฐานะที่เป็นคนที่ใช้sed มากไม่ค่อยต้องการที่สำคัญที่สุดของฉันคือสิ่งที่ฉันได้อย่างรวดเร็วสามารถเข้าใจเมื่อฉันต้องการที่จะแก้ไขได้อย่างง่ายดายหรืออีกจุดประสงค์มันปีนับจากนี้
Jim Grisham

1

สำหรับผู้ที่เลือกที่จะจดจำเฉพาะเครื่องมือพื้นฐานในแต่ละวันและยินดีที่จะยอมรับวิธีการแก้ปัญหาที่ไม่หรูหราและมีประสิทธิภาพน้อยลง:

head -n $(grep -n pattern filename | cut -d: -f1) filename

หากคำสั่งนี้มีไว้สำหรับสคริปต์ฉันจะมองหาโซลูชันที่หรูหราและมีประสิทธิภาพมากขึ้น หากนี่เป็นคำสั่งครั้งเดียวหรือเป็นบทคัดค้านฉันไม่สนใจ


1
เป็นความคิดที่ดี แต่มีสามคำสั่งเมื่อใครจะทำ
มิเคล

1
รู้พื้นฐานเป็นสิ่งที่ดีมากแน่นอน อย่างไรก็ตามการรู้จักเครื่องมือที่เหมาะสมสำหรับงานนั้นดีกว่า
Soulmerge

หากคำสั่งนี้มีไว้สำหรับสคริปต์ฉันจะมองหาโซลูชันที่หรูหราและมีประสิทธิภาพมากขึ้น หากนี่เป็นคำสั่งครั้งเดียว (หรือสคริปต์การโยนทิ้งไป) ฉันก็ไม่สนใจ
lesmana

0

คุณสามารถใช้วิธีใดวิธีหนึ่งต่อไปนี้

tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac 

หรือ

tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac

หรือ

tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac

ตัวเลือกแรกคล้ายกับสิ่งที่ OP แนะนำเท่านั้นทำให้แน่ใจว่าจะแสดงบรรทัดเพียงพอก่อนบริบทโดยการนับบรรทัดในไฟล์

ตัวเลือกที่สองค้นหาหมายเลขบรรทัดของคู่แรก (คุณสามารถเปลี่ยนได้เช่นกันโดยเปลี่ยน 'หัว' ภายใน) และแทนที่จะใช้หัวกับหมายเลขนั้น

ตัวเลือกสุดท้ายจะแทนที่บรรทัดใหม่ทั้งหมดด้วยการจับคู่และแทนที่การจับคู่สองรายการที่อยู่ติดกันด้วยบรรทัดใหม่ ผลลัพธ์ของสิ่งนี้เป็นบรรทัดสำหรับทุกบล็อคข้อความระหว่างสองรายการที่ตรงกัน หลังจากนั้นจะใช้ 'หัว' เพื่อเลือกบรรทัดแรก (mwaning บล็อกข้อความจนกว่าจะถึงการแข่งขันครั้งแรก) การแข่งขันและกว่า retranslates แต่ละการแข่งขันไปยังบรรทัดใหม่ ตัวเลือกนี้ใช้งานได้เฉพาะเมื่อไฟล์อยู่ในรูปแบบต่อไปนี้

pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern 
texttexttext
texttexttexttexttexttexttexttexttext

และอื่น ๆ


2
ลองพิจารณาอธิบายว่างานเหล่านี้โดยเฉพาะอย่างยิ่งเพราะsedคำสั่งที่อยู่ด้านล่างเป็นแบบ gnarly
strugee

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