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"?
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"?
Câu trả lời:
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
Foovà Barsẽ bao gồm toàn bộ dòng.
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 spacevà hold 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ị.
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
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.
find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
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
-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ị.
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)