ฉันจะ grep ไดเรกทอรีสำหรับบรรทัดที่มี "Foo" แต่จะได้รับการจับคู่เมื่อบรรทัดถัดไปยังมี "บาร์" ด้วย?
ฉันจะ grep ไดเรกทอรีสำหรับบรรทัดที่มี "Foo" แต่จะได้รับการจับคู่เมื่อบรรทัดถัดไปยังมี "บาร์" ด้วย?
คำตอบ:
@ warl0ck ชี้ให้ฉันไปในทิศทางที่ถูกต้องด้วยpcregrepแต่ฉันบอกว่า "มี" ไม่ใช่ "เป็น" และฉันถามเกี่ยวกับไดเรกทอรีไม่ใช่ไฟล์
ดูเหมือนว่าจะใช้งานได้สำหรับฉัน
pcregrep -rMi 'Foo(.*)\n(.*)Bar' .
Grep ตัวเองดูเหมือนจะไม่สนับสนุนให้ใช้ pcregrep แทน:
Foo
Bar
Foo
abc
pcregrep -M "Foo\nBar" file
ได้:
Foo
Bar
FooและBarจะประกอบไปด้วยทั้งบรรทัด
ด้วยsedสคริปต์:
#!/bin/sed -nf
/^Foo/{
h # put the matching line in the hold buffer
n # going to nextline
/^Bar/{ # matching pattern in newline
H # add the line to the hold buffer
x # return the entire paragraph into the pattern space
p # print the pattern space
q # quit the script now
}
}
วิธีใช้:
chmod +x script.sed
printf '%s\n' * | ./script.sed
นี่แสดงไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันในหนึ่งบรรทัดในแต่ละครั้งและผ่านมันไปprintfsed
หมายเหตุ : เรียงลำดับตามตัวอักษร
ข่าวสารอื่น ๆ ที่มีประโยชน์pattern spaceและที่นี่hold space
grymoire.comมีสิ่งที่ดีเกี่ยวกับshellการเขียนโปรแกรม
h, n, H, x, p, qหมายถึง? น่าสนใจมาก.
pattern space& hold space: grymoire.com/Unix/Sed.html#uh-56หรือในภาษาฝรั่งเศสcommentcamarche.net/faq/9536-sed-introduction-a-sed-part-i
ใช้grepเพียงคุณสามารถสร้างไปป์ต่อไปนี้:
grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'
ก่อนgrepจะได้รับทุกบรรทัดที่มีFooเช่นเดียวกับสายหลังการแข่งขัน จากนั้นเราก็จะได้รับสายที่มีเช่นเดียวกับสายก่อนการแข่งขันและในที่สุดก็ดึงสายจากการแสดงผลนี้ที่มีBarFoo
แก้ไข:ตามที่การผลิตชี้ให้เห็นมีบางกรณีที่มีปัญหาที่จะเป็นช่างสังเกต แม้ว่าจะมีความท้าทายที่น่าสนใจเนื่องจากgrepฟังก์ชั่นที่มุ่งเน้นการทำงานของสายการแก้ปัญหาใด ๆ ที่มีแนวโน้มว่าจะเป็น 'แฮ็ค' และคุณควรใช้สิ่งpcregrepที่เหมาะกับงานในมือมากกว่า
find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
ในขณะที่ฉันชอบโซลูชันของ Nathan pcregrepมากกว่านี่คือวิธีแก้ปัญหาโดยใช้ grep เท่านั้น
grep -o -z -P 'Foo(.*)\n(.*)Bar' file
คำอธิบายตัวเลือก:
-oพิมพ์เฉพาะส่วนที่จับคู่ จำเป็นเนื่องจากจะรวม-zจะพิมพ์ไฟล์ทั้งหมด (ยกเว้นว่ามี \ 0 บางแห่ง)-z ใช้อินพุตเป็นชุดของบรรทัดแต่ละบรรทัดถูกยกเลิกด้วยศูนย์ไบต์ (อักขระ ASCII NUL) แทนบรรทัดใหม่-P ไวยากรณ์ perl regex แก้ไข: รุ่นนี้พิมพ์เส้นที่ตรงกันทั้งหมด
grep -o -P -z '(.*)Foo(.*)\n(.*)Bar(.*)' file
-zๆ บาง“ (. *)” ก่อนและหลังการแสดงออกทั้งหมดจะทำให้มันออกเส้นที่ตรงกันทั้งหมด สำหรับวัสดุพิมพ์ก่อนหน้า“ Foo” และหลังจาก“ Bar” จะไม่แสดงขึ้นมา
ด้วย awk:
awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
/foo/ {prev=$0; next}
{prev=""}' file1...
(หมายเหตุทั่วไปเกี่ยวกับข้อ จำกัด awk: โปรดระวังว่าหากชื่อไฟล์บางชื่ออาจมีอักขระ "=" คุณจะต้องผ่านมัน./filenameแทนfilenameการ awk)