ฉันจะ grep ไดเรกทอรีตามเนื้อหาของสองบรรทัดต่อเนื่องได้อย่างไร


11

ฉันจะ grep ไดเรกทอรีสำหรับบรรทัดที่มี "Foo" แต่จะได้รับการจับคู่เมื่อบรรทัดถัดไปยังมี "บาร์" ด้วย?


ขณะนี้ปัญหาแตกต่างจากของเดิมโดยสิ้นเชิง: / อาจจะดีกว่าที่จะคืนค่าเวอร์ชันเก่า & โพสต์อีกอันหนึ่ง? ยิ่งไปกว่านั้นคำถามใหม่ยังไม่ชัดเจนสำหรับฉัน
Gilles Quenot

@ sputnick - เป็นอย่างไร ฉันระบุไดเรกทอรีเมื่อฉันโพสต์คำถามครั้งแรก; ฉันทำตัวหนาเพราะคนไม่สังเกตุ
นาธานลอง

ไม่เป็นไรฉันจะแก้ไข POST ตามนั้น
Gilles Quenot

คำตอบ:


7

@ warl0ck ชี้ให้ฉันไปในทิศทางที่ถูกต้องด้วยpcregrepแต่ฉันบอกว่า "มี" ไม่ใช่ "เป็น" และฉันถามเกี่ยวกับไดเรกทอรีไม่ใช่ไฟล์

ดูเหมือนว่าจะใช้งานได้สำหรับฉัน

pcregrep -rMi 'Foo(.*)\n(.*)Bar' .

6

Grep ตัวเองดูเหมือนจะไม่สนับสนุนให้ใช้ pcregrep แทน:

Foo
Bar
Foo
abc

pcregrep -M "Foo\nBar" file

ได้:

Foo
Bar

3
OP ไม่ได้พูดอย่างนั้นFooและBarจะประกอบไปด้วยทั้งบรรทัด
tojrobinson

6

ด้วย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หมายถึง? น่าสนใจมาก.
Yamaneko

ดูความคิดเห็นของฉัน ข่าวสารเพิ่มเติมเกี่ยวกับpattern space& hold space: grymoire.com/Unix/Sed.html#uh-56หรือในภาษาฝรั่งเศสcommentcamarche.net/faq/9536-sed-introduction-a-sed-part-i
Gilles Quenot

POST ปรับตัวให้ทำงานในไดเรกทอรี
Gilles Quenot

4

ใช้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'
นานนาธาน

ที่จะแสดงรายการที่เกิดขึ้นกับทั้ง "Foo" และ "บาร์" ในบรรทัดเดียวกัน
จัดการ

@ manatwork: บรรทัดที่มี "Foo" และ "Bar" คือ "บรรทัดที่มี 'Foo'" ซึ่งเป็นสิ่งที่ถูกถาม
tojrobinson

1
@tojrobinson แล้วส่วน "แต่จะได้รับการจับคู่เมื่อบรรทัดถัดไปมีส่วน" บาร์ "เท่านั้น? pastebin.com/Yj8aeCEA
จัดการ

3

ในขณะที่ฉันชอบโซลูชันของ 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

1
เคล็ดลับเด็ด-zๆ บาง“ (. *)” ก่อนและหลังการแสดงออกทั้งหมดจะทำให้มันออกเส้นที่ตรงกันทั้งหมด สำหรับวัสดุพิมพ์ก่อนหน้า“ Foo” และหลังจาก“ Bar” จะไม่แสดงขึ้นมา
จัดการ

1

ด้วย awk:

awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
     /foo/ {prev=$0; next}
     {prev=""}' file1...

(หมายเหตุทั่วไปเกี่ยวกับข้อ จำกัด awk: โปรดระวังว่าหากชื่อไฟล์บางชื่ออาจมีอักขระ "=" คุณจะต้องผ่านมัน./filenameแทนfilenameการ awk)

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