Grep chỉ trận đấu đầu tiên và dừng lại


328

Tôi đang tìm kiếm một thư mục đệ quy bằng grep với các đối số sau với hy vọng chỉ trả về kết quả khớp đầu tiên. Thật không may, nó trả về nhiều hơn một - thực tế là hai lần cuối cùng tôi nhìn. Có vẻ như tôi có quá nhiều tranh luận, đặc biệt là không có được kết quả mong muốn. : - /

# grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/directory

trả về:

Pulsanti Operietur
Pulsanti Operietur

Có lẽ grep không phải là cách tốt nhất để làm điều này? Bạn nói với tôi, cảm ơn rất nhiều.

Câu trả lời:


510

-m 1có nghĩa là trả lại trận đấu đầu tiên trong bất kỳ tập tin nào. Nhưng nó vẫn sẽ tiếp tục tìm kiếm trong các tập tin khác. Ngoài ra, nếu có hai hoặc nhiều kết quả khớp trong cùng một dòng, tất cả chúng sẽ được hiển thị.

Bạn có thể sử dụng head -1để giải quyết vấn đề này:

grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -1

giải thích về từng tùy chọn grep:

-o, --only-matching, print only the matched part of the line (instead of the entire line)
-a, --text, process a binary file as if it were text
-m 1, --max-count, stop reading a file after 1 matching line
-h, --no-filename, suppress the prefixing of file names on output
-r, --recursive, read all files under a directory recursively

tuyệt vời! cảm ơn bạn. btw - tất cả những đối số khác cần thiết mà tôi có trong lệnh? và nếu tôi không thể đặt nó một cách tình cờ (chỉ trong trường hợp).
Tim Kamm

2
Tôi không nghĩ rằng chúng là cần thiết (ngoại trừ -rrõ ràng), nhưng chúng không nên làm tổn thương ( -amặc dù tôi sẽ không sử dụng )
mvp

3
Chính xác những gì tôi cần. Mẫu của tôi đã được tìm thấy hai lần trên cùng một dòng và grep -m 1trả về cả hai trường hợp vì điều này. |head -1đã giải quyết nó
harperville

6
@Chris_Rands hành vi chính xác phụ thuộc vào shell mà bạn đang chạy. Head sẽ thoát ngay khi gặp dòng đầu tiên. grep sẽ thoát lần sau khi nó cố viết sau khi thoát khỏi đầu. Một số vỏ sẽ đợi cho đến khi tất cả các yếu tố của một đường ống kết thúc, một số sẽ khiến toàn bộ đường ống bị tắt ngay khi chương trình cuối cùng trong đường ống thoát ra.
puhlen

1
@ 3Qn, tôi không hiểu bình luận của bạn : first not first from result. Câu trả lời này in trận đấu đầu tiên trong bất kỳ tập tin và dừng lại. bạn đã mong đợi điều gì khác?
mvp

31

Bạn có thể dẫn grepkết quả đến headkết hợp với stdbuf .

Lưu ý, để đảm bảo dừng sau trận đấu thứ N, bạn cần sử dụng stdbufđể đảm bảo grepkhông đệm đầu ra của nó:

stdbuf -oL grep -rl 'pattern' * | head -n1
stdbuf -oL grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -n1
stdbuf -oL grep -nH -m 1 -R "django.conf.urls.defaults" * | head -n1

Ngay khi headtiêu thụ 1 dòng, nó đã chấm dứt và grepsẽ nhận được SIGPIPEvì nó vẫn xuất ra thứ gì đó cho đường ống trong khi headđã biến mất.

Điều này giả định rằng không có tên tập tin có chứa dòng mới.


Tôi đang cố gắng áp dụng giải pháp này để tìm kiếm trong một số lượng lớn tệp lưu trữ với xargs:find . -name '*.gz' | xargs -I '{}' stdbuf -oL zgrep -al 'pattern' {} | head -n 1 . Điều này, tuy nhiên, không chấm dứt trong trận đấu đầu tiên. Có lời khuyên nào không?
DKroot

1
Sẽ không grep's --line-bufferedtùy chọn ngăn chặn đệm overhead mà không gọi một tiện ích bổ sung?
David

23

Chương trình grep-a-like của tôi ack có một -1tùy chọn dừng ở trận đấu đầu tiên được tìm thấy ở bất cứ đâu. Nó cũng hỗ trợ -m 1@mvp. Tôi đặt nó ở đó bởi vì nếu tôi đang tìm kiếm một cây mã nguồn lớn để tìm thứ gì đó mà tôi biết chỉ tồn tại trong một tệp, thì không cần thiết phải tìm nó và phải nhấn Ctrl-C.


Vì vậy, bạn sẽ nói rằng ack nhanh hơn grep? Tôi thực sự quan tâm đến yếu tố tốc độ.
Tim Kamm

1
ack có thể nhanh hơn grep, tùy thuộc vào những gì bạn đang tìm kiếm. Xin lưu ý rằng ack là về tìm kiếm mã nguồn. Nếu bạn đang tìm kiếm các tệp chung, điều đó sẽ không tốt lắm, ít nhất là trong ack 1.x. Đi đọc về ack và xem có thể nó phù hợp với nhu cầu của bạn.
Andy Lester

2
Tôi đã sử dụng Ack được một thời gian dài nhưng gần đây đã chuyển sang Công cụ tìm kiếm bạc mà tôi thấy là nhanh hơn Ack
guys.gc

Tôi tin rằng đây chỉ là câu trả lời duy nhất vì OP nói rằng anh ta muốn nó được thực hiện với grep, nhưng câu trả lời khác sử dụng đầu (tất nhiên là cả hai công việc) nhưng có một số môi trường được nhúng / tự tạo với các công cụ tối thiểu trong đó grep là phổ biến và đuôi / đầu thì không.
Areeb Soo Yasir

Đáng nói là agcó thể nhanh, nhưng nó không-1tùy chọn hữu ích trong trường hợp này
jja

3

Bạn có thể sử dụng lệnh dưới đây nếu bạn muốn in toàn bộ dòng và tên tệp nếu sự xuất hiện của từ cụ thể trong thư mục hiện tại bạn đang tìm kiếm.

grep -m 1 -r "Not caching" * | head -1

2

Một lớp lót duy nhất, sử dụng find:

find -type f -exec grep -lm1 "PATTERN" {} \; -a -quit

6
Điều này sẽ rất chậm, vì find sẽ sinh ra bản sao của grep cho mỗi tệp được tìm thấy. grep -rhoạt động nhanh hơn rất nhiều - chỉ có một bản sao thực hiện duyệt qua thư mục.
mvp

Thật; mặc dù find có thể được tùy chỉnh để chỉ hoạt động trên các kết quả được lọc, sau đó có thể làm cho hoạt động nhanh hơn nhiều so với grep bắt tất cả. Phụ thuộc vào bối cảnh.
Yam Marcovic
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.