Làm thế nào tôi có thể grep một thư mục dựa trên nội dung của hai dòng liên tiếp?


11

Làm cách nào tôi có thể grep một thư mục cho các dòng có chứa "Foo", nhưng chỉ nhận được kết quả khớp khi dòng tiếp theo cũng chứa "Bar"?


Vấn đề bây giờ hoàn toàn khác so với bản gốc: / Có thể tốt hơn để hoàn nguyên các phiên bản cũ & POST một phiên bản khác? Hơn nữa, câu hỏi mới không rõ ràng đối với tôi.
Gilles Quenot

@sputnick - Làm sao vậy? Tôi đã chỉ định một thư mục khi lần đầu tiên tôi đăng câu hỏi; Tôi chỉ in đậm vì mọi người không chú ý.
Nathan Long

Nevermind, nó sẽ hoạt động, tôi sẽ chỉnh sửa POST của tôi cho phù hợp.
Gilles Quenot

Câu trả lời:


7

@ warl0ck chỉ cho tôi đi đúng hướng pcregrep, nhưng tôi nói "chứa", không phải "là", và tôi đã hỏi về một thư mục, không phải là một tập tin.

Điều này dường như làm việc cho tôi.

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

6

Bản thân Grep dường như không hỗ trợ nó, thay vào đó hãy sử dụng pcregrep:

Foo
Bar
Foo
abc

pcregrep -M "Foo\nBar" file

Có:

Foo
Bar

3
OP đã không nói điều đó FooBarsẽ bao gồm toàn bộ dòng.
tojrobinson

6

Với một sedkịch bản:

#!/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
    }
}

Để dùng nó :

chmod +x script.sed
printf '%s\n' * | ./script.sed

printfđây hiển thị tất cả các tệp trong thư mục hiện tại trên mỗi dòng và truyền nó cho sed.

Lưu ý : điều này được sắp xếp theo thứ tự bảng chữ cái.

Thêm infos hữu ích pattern spacehold space TẠI ĐÂY .

grymoire.com có những thứ thực sự tốt về shelllập trình.


h, n, H, x, p, qnghĩa là gì? Rất thú vị.
Yamaneko

Xem ý kiến ​​của tôi. Thêm thông tin về pattern space& hold space: grymoire.com/Unix/Sed.html#uh-56 hoặc bằng tiếng Pháp commentcamarche.net/faq/9536-sed-int sinhtion
Gilles Quenot

POST thích nghi để làm việc trên một thư mục
Gilles Quenot

4

grepChỉ sử dụng , bạn có thể xây dựng đường ống sau:

grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'

Đầu tiên grepsẽ nhận được tất cả các dòng có chứa Foocũng như dòng sau trận đấu. Sau đó, chúng tôi nhận được các dòng có chứa Barcũng như dòng trước trận đấu, và cuối cùng trích xuất các dòng từ đầu ra này có chứa Foo.

EDIT: Như manatwork đã chỉ ra, có một số trường hợp có vấn đề cần phải quan sát. Mặc dù là một thách thức thú vị, do grepchức năng định hướng theo dòng, bất kỳ giải pháp nào có thể là 'hack' và bạn có thể tốt hơn khi sử dụng thứ gì pcregrepđó phù hợp hơn với nhiệm vụ trong tay.


Đẹp. Tôi đã hỏi về một thư mục mặc dù; điều này có vẻ hiệu quả:find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
Long Long

Điều đó cũng sẽ liệt kê các lần xuất hiện với cả hai dòng Foo và và Bar Bar trên cùng một dòng.
manatwork

@manatwork: Các dòng chứa "Foo" và "Bar" là "các dòng chứa 'Foo'", đó là những gì được hỏi.
tojrobinson

1
@tojrobinson, thế còn những người khác nhưng chỉ nhận được các trận đấu khi dòng tiếp theo cũng chứa phần "Bar" thì sao? pastebin.com/Yj8aeCEA
manatwork

3

Mặc dù tôi thích giải pháp của Nathan hơn pcregrep, nhưng đây là giải pháp chỉ sử dụng grep

grep -o -z -P  'Foo(.*)\n(.*)Bar' file

Tùy chọn giải thích:

  • -ochỉ in một phần phù hợp. Cần thiết vì bao gồm -zsẽ in ra toàn bộ tệp (trừ khi có \ 0 ở đâu đó)
  • -z Coi đầu vào là một tập hợp các dòng, mỗi dòng được kết thúc bằng một byte 0 (ký tự ASCII NUL) thay vì một dòng mới.
  • -P cú pháp regl perl

EDIT: Phiên bản này in ra toàn bộ dòng phù hợp

    grep -o -P -z  '(.*)Foo(.*)\n(.*)Bar(.*)' file

1
Tuyệt chiêu gì -z. Một số người ((* *) trước và sau toàn bộ biểu thức sẽ làm cho nó xuất ra toàn bộ các dòng khớp. Cho đến bây giờ, các chuỗi con trước khi FASH Foo và sau khi Bar Bar không được hiển thị.
manatwork

1

Với awk:

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

(lưu ý chung về giới hạn awk: hãy cẩn thận rằng nếu một số tên tệp có thể chứa các ký tự "=", bạn sẽ cần chuyển chúng ./filenamethay vì filenameđể awk)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.