Grep multiline pattern


13

ฉันจะค้นหาวลีผ่านหลายบรรทัดได้อย่างไร เช่นช่วยให้มีวลี "ชาน้ำแข็งของฉัน" จากนั้นก็อาจถูกห่อในไฟล์ข้อความ:

as js skdfh dfh djh sf my
ice tea.

grep จะไม่ตรงกันเนื่องจากมีการขึ้นบรรทัดใหม่ในระหว่าง ฉันจะจับคู่เหล่านั้นได้อย่างไร อีกรูปแบบหลายบรรทัดก็จะเป็นpattern1_\n_pattern2

ฉันรู้ว่าวิธีที่ง่ายที่สุดที่ฉันทำตู้เอทีเอ็มเป็นเพียง grep สำหรับส่วนหนึ่งเช่นเพียงแค่น้ำแข็งกับธง -A2 -B2 และจากนั้นในการส่งออก againg เช่นชา แต่นี่น่าเบื่อมาก ดังนั้นฉันจึงถูกขัดจังหวะว่าคุณจะแก้ปัญหานี้อย่างไร


1
ไซต์ข้ามที่เป็นไปได้ซ้ำซ้อนของ: stackoverflow.com/questions/152708/ …
Ciro Santilli 事件改造中心中心法轮功六四事件

คำตอบ:


16

คุณสามารถติดตั้งpcregrep(มีอยู่ในที่เก็บ distro ส่วนใหญ่) - ซึ่งเป็น grep โดยใช้ไลบรารี่ pcreซึ่งทำหน้าที่ "Perl Compatible Regular Expressions" มันมีตัวเลือกบรรทัดคำสั่ง-Mที่ช่วยให้คุณทำการค้นหาหลายบรรทัด- จากหน้าคน :

"ผลลัพธ์สำหรับการจับคู่ใด ๆ อาจประกอบด้วยมากกว่าหนึ่งบรรทัด"

ดังนั้นคุณสามารถทำได้

pcregrep -M 'my\s+ice\s+tea' filename

The \sคือช่องว่างซึ่งจะจับคู่\nและ\rในโหมดหลายบรรทัดนอกเหนือจากอักขระช่องว่างปกติ คุณยังสามารถจับคู่อักขระบรรทัดใหม่ได้โดยตรงดังนั้นคุณสามารถทำได้

pcregrep -M 'pattern1_\n_pattern2' filename

+1 ดี ไม่เคยได้ยิน แต่ทดลองและใช้งานได้เหมือนมีเสน่ห์!
DaveParillo

grep -Eรูปแบบ pcre ไม่ได้ทำ?
Daenyth

3
@Daenyth grep -E ส่วนใหญ่ก็หมายความว่าคุณสามารถใช้ ?, +, {, |, (และ)เป็นความหมาย regex ปกติของพวกเขาได้โดยไม่ต้องมี\ ในด้านหน้าเป็นคุณจะทำอย่างไรถ้าคุณใช้ grep มาตรฐาน ดังนั้นจะเทียบเท่ากับgrep 'hello\s\+world' file grep -E 'hello\s+world' fileมันไม่ได้ทำ PCRE มีgrep -Pสำหรับการแสดงออกปกติ Perl แต่มันคือการทดลอง (ตามหน้าคน) และฉันคิดว่ามันแตกต่างกันเล็กน้อยจาก pcregrep ...
Hamish Downer

1
ใช่ฉันคิดถึง-Pตอนที่ฉันพูด-Eแต่ฉันก็ไม่ได้ตระหนักว่ามันแตกต่างกัน
Daenyth

3

ฉันอาจจะทำการค้นหาโดยใช้vim's :vimgrepคำสั่ง วิธีนี้ใช้งานได้ในลักษณะที่คล้ายคลึงกับของgrepแต่สนับสนุนกลุ่มตัวอย่างและเส้นทางที่เป็นกลุ่ม

โดยทั่วไปคุณเรียกใช้สิ่งที่ต้องการ:vimgrep 'pattern1\npattern2' path/**สำหรับการค้นหาแบบเรียกซ้ำแล้วพิมพ์:copenเพื่อเปิดหน้าต่างเล็ก ๆ ที่มีรายการการแข่งขัน

vimREs สามารถทำทุกอย่างเป็นส่วนใหญ่ที่ PCREs ทำได้ แต่พวกมันพัฒนาแยกต่างหากจากเชื้อสายการแสดงออกปกติของ Perl ดังนั้นสิ่งที่ก้าวหน้าส่วนใหญ่จะทำงานต่างกัน ฟังก์ชั่นพื้นฐานของพวกเขานั้นคล้ายกับ REs พื้นฐาน แต่มีคุณสมบัติเพิ่มเติมที่ PCREs ไม่มีให้

ผมไม่แน่ใจว่าถ้ามันเป็นไปได้ที่จะได้รับ:vimgrepที่จะคายออกมาเป็นข้อมูลgrepไม่; ฉันเคยลองใช้มันเพื่อนำทางภายในvimเท่านั้น

:help vimgrepจากภายในvimสำหรับข้อมูลเพิ่มเติม; :help pattern.txtสำหรับข้อมูลเกี่ยวกับvimREs; :help wildcardsสำหรับข้อมูลเพิ่มเติมเกี่ยวกับเส้นทางที่เห็น


ระวัง - มันไม่ได้พกพาได้ทั้งหมดเพราะมันจะมีพฤติกรรมแตกต่างกันไปในแต่ละแพลตฟอร์ม
Daenyth

1
@Daenyth: คุณหมายถึงภายใต้อิทธิพลของคนอื่น.vimrcหรือไม่? ควรพกพาได้มากกว่าgrepระบบปฏิบัติการ: vimไม่มี "POSIX รส" และทำงานได้เหมือนกันแม้ใน Windows .................................................. ........................... เป็นไปได้ที่จะเพิ่มตัวระบุเพื่อให้แน่ใจว่าในปริมาณที่เหมาะสมของ "เวทย์มนตร์" จะถูกใช้ใน RE แม้ว่า ในขณะที่ฉันเข้าใจว่ามีกฎที่ไม่ได้เขียนไว้อย่างเข้มงวดเพื่อปล่อยให้ตัวเลือกนั้นเป็นห่า
intuited

ฉันไม่ได้ใช้ด้วยตนเอง แต่เห็นได้ชัดว่ามันใช้แบ็กเอนด์อื่นบน windows ( find.exeแทนgrep) มีคำถามอื่นภายในสองสามสัปดาห์ที่ผ่านมาที่มีปัญหา
Daenyth

1
@Daenyth: คุณคิดว่าการ:vimgrepหรือ:grep? จาก:help grep: "ข้อดีของ grep ภายใน [ie :vimgrep] คือทำงานได้กับทุกระบบและใช้รูปแบบการค้นหา Vim อันทรงพลัง"
intuited

1
อานั่นต้องเป็นแน่ ฉันทั้งสองสับสน
Daenyth

2

Grep ใช้งานได้ครั้งละหนึ่งบรรทัดเท่านั้น แต่คุณสามารถใช้ awk เพื่อพิมพ์บรรทัดที่ตรงกับช่วงของรูปแบบ:

cat file | awk '/foo/,/bar/'

มันจะจับคู่กับอะไรก็ได้ไม่ใช่แค่การขึ้นบรรทัดใหม่ระหว่างสองรูปแบบ


0

เพื่อให้ได้ประโยชน์สูงสุดจากยูนิกซ์คุณต้องใช้ประโยชน์จากท่อ คุณสามารถทำได้grepโดยใช้ไพพ์ (ไม่จำเป็นต้องมีที)

$ grep -A1 "pattern1" file.txt |  grep "pattern2"

ซึ่งฉันไม่คิดว่าน่าเบื่อ


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