ฉันจะ 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
นี่แสดงไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันในหนึ่งบรรทัดในแต่ละครั้งและผ่านมันไปprintf
sed
หมายเหตุ : เรียงลำดับตามตัวอักษร
ข่าวสารอื่น ๆ ที่มีประโยชน์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
เช่นเดียวกับสายหลังการแข่งขัน จากนั้นเราก็จะได้รับสายที่มีเช่นเดียวกับสายก่อนการแข่งขันและในที่สุดก็ดึงสายจากการแสดงผลนี้ที่มีBar
Foo
แก้ไข:ตามที่การผลิตชี้ให้เห็นมีบางกรณีที่มีปัญหาที่จะเป็นช่างสังเกต แม้ว่าจะมีความท้าทายที่น่าสนใจเนื่องจาก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)