grep --before-context 5
แสดง 5 บรรทัดก่อนการแข่งขัน
ฉันต้องการแสดงทุกอย่างก่อนการแข่งขัน
การgrep --before-context 99999999
ทำงานจะได้ผล แต่มันไม่ได้เป็นมืออาชีพมากนัก
วิธีการแสดงไฟล์ทั้งหมดถึงการแข่งขัน?
grep --before-context 5
แสดง 5 บรรทัดก่อนการแข่งขัน
ฉันต้องการแสดงทุกอย่างก่อนการแข่งขัน
การgrep --before-context 99999999
ทำงานจะได้ผล แต่มันไม่ได้เป็นมืออาชีพมากนัก
วิธีการแสดงไฟล์ทั้งหมดถึงการแข่งขัน?
คำตอบ:
Sedดีกว่าสำหรับเรื่องนั้น
แค่ทำ:
sed '/PATTERN/q' FILE
มันได้ผลเช่นนี้:
สำหรับแต่ละบรรทัดเราจะดูว่าตรงกันหรือไม่/PATTERN
:
นี้เป็นทางออกที่มีประสิทธิภาพมากที่สุดเพราะทันทีที่เห็นPATTERN
ก็หยุดทำงาน หากไม่มีq
sed จะอ่านไฟล์ที่เหลือต่อไปและไม่ทำอะไรกับมันเลย สำหรับไฟล์ขนาดใหญ่มันสามารถสร้างความแตกต่าง
เคล็ดลับนี้ยังสามารถใช้เพื่อเลียนแบบhead
:
sed 10q FILE
sed '/PATTERN/Q' FILE
จะข้ามบรรทัดที่ตรงกัน Q
เป็นส่วนขยายของ GNU ดังนั้นจึงไม่สามารถทำงานกับ sed ใด ๆ
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
พิมพ์ได้ถึงและรวมถึงการแข่งขัน:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
พิมพ์ได้สูงสุด แต่ไม่รวมการจับคู่:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Q
เจ๋ง แต่ gnu เฉพาะ afaik sed -n '/pattern/!p;//q'
จะพกพาได้มากกว่านี้
!
ทำให้p
ใช้กับบรรทัดที่ไม่ตรงกันpattern
แต่แล้ว//q
ฉันสับสน ...
//
หมายถึง "นิพจน์ปกติก่อนหน้า" (ฉันคิดว่ามันหมายถึง "จับคู่สตริงว่าง") ผมคิดว่ารุ่นสั้นของการแก้ปัญหาเดียวกันคือsed -n '/pattern/q;p
?
grep
วิธีGNU ล้วนๆดังต่อไปนี้ไม่มีประสิทธิภาพ
ค้นหาทุกอย่างจนถึงอินสแตนซ์แรกของสตริง " foo " ในแถบไฟล์โดยใช้สามgrep
s:
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) สำหรับการค้นหาหลายสายที่จำเป็น
grep
วินาที (+ pcre) เมื่อเป็นเรื่องของการเรียกใช้เพียงครั้งเดียวsed
: sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'
??
sed
ดูเหมือนว่ารหัสของคุณจะคุ้มค่ากับคำตอบของตัวเองหรือสามารถเพิ่มลงในรายการอื่น Re 7 grep
s: เนื่องจากไม่มีgrep
คำตอบ ... (บวกคำตอบช่วยแสดงว่าทำไมถึงไม่)
กำลังเพิ่มลงในคำตอบของ Mikel ด้านบน ...
หากต้องการพิมพ์บรรทัดทั้งหมดจนถึง แต่ไม่รวมบรรทัดแรกในFILE
ที่มีPATTERN
ให้ลอง:
sed '/.*PATTERN.*/{s///;q;}' FILE
สิ่งนี้ตรงกับทั้งบรรทัดที่มีรูปแบบแทนที่ด้วยบรรทัดว่างจากนั้นออกโดยไม่ต้องดำเนินการกับไฟล์ที่เหลือ
โพสต์สคริปต์:
วิธีที่ง่ายที่สุด / ชัดเจนที่สุดที่ฉันสามารถคิดได้เพื่อป้องกันการพิมพ์บรรทัดใหม่พิเศษในตอนท้าย (โดยไม่เกี่ยวข้องกับเครื่องมืออื่น) คือการทำงานอีกครั้งและลบบรรทัดสุดท้ายใหม่:
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
... และเนื่องจากตอนนี้เรากำลังลบบรรทัดนั้นอยู่ผลงานก่อนหน้าของเราซ้ำซ้อนและเราสามารถทำให้:
sed '/PATTERN/q' FILE | sed '$d'
sed
เรียกใช้เพียงครั้งเดียว
tcsh
และbash
นามแฝงฉันต้องแน่ใจว่าฉัน มีโซลูชันบรรทัดเดียวที่ค่อนข้างกระชับซึ่งทำงานได้ทั้งแบบมาตรฐานและ GNU sed
(สำหรับการพกพา); ข้อกำหนดทั้งหมดที่การบริจาคของคุณอาจปฏิบัติตามได้เป็นอย่างดี ในฐานะที่เป็นคนที่ใช้sed
มากไม่ค่อยต้องการที่สำคัญที่สุดของฉันคือสิ่งที่ฉันได้อย่างรวดเร็วสามารถเข้าใจเมื่อฉันต้องการที่จะแก้ไขได้อย่างง่ายดายหรืออีกจุดประสงค์มันปีนับจากนี้
สำหรับผู้ที่เลือกที่จะจดจำเฉพาะเครื่องมือพื้นฐานในแต่ละวันและยินดีที่จะยอมรับวิธีการแก้ปัญหาที่ไม่หรูหราและมีประสิทธิภาพน้อยลง:
head -n $(grep -n pattern filename | cut -d: -f1) filename
หากคำสั่งนี้มีไว้สำหรับสคริปต์ฉันจะมองหาโซลูชันที่หรูหราและมีประสิทธิภาพมากขึ้น หากนี่เป็นคำสั่งครั้งเดียวหรือเป็นบทคัดค้านฉันไม่สนใจ
คุณสามารถใช้วิธีใดวิธีหนึ่งต่อไปนี้
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
และอื่น ๆ
sed
คำสั่งที่อยู่ด้านล่างเป็นแบบ gnarly