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
Foo
và Bar
sẽ bao gồm toàn bộ dòng.
Với một sed
kị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 space
và hold space
TẠI ĐÂY .
grymoire.com có những thứ thực sự tốt về shell
lập trình.
h, n, H, x, p, q
nghĩ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
grep
Chỉ 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 grep
sẽ nhận được tất cả các dòng có chứa Foo
cũng như dòng sau trận đấu. Sau đó, chúng tôi nhận được các dòng có chứa Bar
cũ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 grep
chứ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:
-o
chỉ in một phần phù hợp. Cần thiết vì bao gồm -z
sẽ 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 ./filename
thay vì filename
để awk)