Grep hanya pertandingan pertama dan berhenti

329

Saya mencari direktori secara rekursif menggunakan grep dengan argumen berikut berharap hanya mengembalikan pertandingan pertama. Sayangnya, ia mengembalikan lebih dari satu - bahkan dua yang terakhir kali saya lihat. Sepertinya saya punya terlalu banyak argumen, terutama tanpa mendapatkan hasil yang diinginkan. : - /

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

pengembalian:

Pulsanti Operietur
Pulsanti Operietur

Mungkin grep bukan cara terbaik untuk melakukan ini? Anda memberi tahu saya, terima kasih banyak.

Tim Kamm
sumber

Jawaban:

512

-m 1berarti mengembalikan kecocokan pertama dalam file apa pun yang diberikan. Tetapi masih akan terus mencari di file lain. Juga, jika ada dua atau lebih yang cocok di baris yang sama, semuanya akan ditampilkan.

Anda dapat menggunakan head -1untuk memecahkan masalah ini:

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

penjelasan dari setiap opsi 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
mvp
sumber
luar biasa! Terima kasih. btw - apakah semua argumen lain yang perlu saya miliki dalam perintah? dan bagaimana jika saya tidak bisa menyalurkannya secara kebetulan (untuk berjaga-jaga).
Tim Kamm
2
Saya tidak berpikir mereka diperlukan (kecuali -rjelas), tetapi mereka tidak boleh terluka (saya tidak akan menggunakan -ameskipun)
mvp
3
Apa yang saya butuhkan. Pola saya ditemukan dua kali pada baris yang sama dan grep -m 1mengembalikan kedua instance karena ini. |head -1dipecahkan!
Harperville
6
@Chris_Rands perilaku yang tepat tergantung pada shell yang Anda jalankan masuk. Kepala akan keluar segera setelah bertemu dengan baris pertama. grep akan keluar saat berikutnya ia mencoba menulis setelah head keluar. Beberapa kerang akan menunggu sampai semua elemen dari pipa selesai, beberapa akan menyebabkan seluruh pipa mati segera setelah program terakhir dalam pipa keluar.
puhlen
1
@ 3QN, saya tidak mengerti komentar Anda: first not first from result. Jawaban ini mencetak kecocokan pertama dalam file apa pun dan berhenti. Apa lagi yang Anda harapkan?
mvp
31

Anda dapat mengirimkangrep hasil ke headdalam hubungannya dengan stdbuf .

Perhatikan, bahwa untuk memastikan penghentian setelah kecocokan ke-N, Anda harus menggunakan stdbufuntuk memastikan grepjangan menyangga outputnya:

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

Begitu headmengkonsumsi 1 baris, itu dihentikan dan grepakan menerima SIGPIPEkarena masih mengeluarkan sesuatu ke pipa saat headhilang.

Ini diasumsikan bahwa tidak ada nama file yang mengandung baris baru.

Venkat Kotra
sumber
Saya mencoba untuk mengadopsi solusi ini untuk mencari di sejumlah besar file arsip dengan xargs: find . -name '*.gz' | xargs -I '{}' stdbuf -oL zgrep -al 'pattern' {} | head -n 1. Namun, ini tidak berakhir pada pertandingan pertama. Ada saran?
DKroot
1
Tidak akan grep's --line-bufferedpilihan mencegah penyangga kepala tanpa memanggil utilitas tambahan?
David
23

Program grep-a-like saya ack memiliki -1opsi yang berhenti pada kecocokan pertama yang ditemukan di mana saja. Ini mendukung -m 1yang mengacu pada @mvp juga. Saya meletakkannya di sana karena jika saya mencari pohon kode sumber yang besar untuk menemukan sesuatu yang saya tahu hanya ada dalam satu file, tidak perlu menemukannya dan harus menekan Ctrl-C.

Andy Lester
sumber
jadi Anda akan mengatakan bahwa ack lebih cepat daripada grep? Saya sangat peduli dengan faktor kecepatan juga.
Tim Kamm
1
ack bisa lebih cepat daripada grep, tergantung pada apa yang Anda cari. Harap dicatat bahwa ack adalah tentang mencari kode sumber. Jika Anda mencari untuk mencari file-file umum, itu kurang bagus, setidaknya di ack 1.x. Baca tentang ACK dan lihat apakah mungkin itu sesuai dengan kebutuhan Anda.
Andy Lester
2
Saya telah menggunakan Ack untuk waktu yang lama tetapi baru-baru ini beralih ke
Pencarian
Saya percaya ini harus menjadi satu-satunya jawaban karena OP mengatakan dia ingin itu dilakukan dengan grep, tetapi jawaban lain menggunakan kepala (keduanya bekerja tentu saja) tetapi ada beberapa lingkungan yang tertanam / dibuat sendiri dengan alat minimal di mana grep adalah umum dan ekor / kepala tidak.
Areeb Soo Yasir
Layak disebutkan yang agmungkin cepat, tetapi tidak memiliki -1opsi yang berguna dalam kasus ini
jja
4

Anda dapat menggunakan perintah di bawah ini jika Anda ingin mencetak seluruh baris dan nama file jika kemunculan kata tertentu dalam direktori saat ini yang Anda cari.

grep -m 1 -r "Not caching" * | head -1
Gaurav londhe
sumber
2

Satu liner, menggunakan find:

find -type f -exec grep -lm1 "PATTERN" {} \; -a -quit
Yam Marcovic
sumber
6
Ini akan menjadi sangat lambat, karena find akan menelurkan salinan grep untuk setiap file yang ditemukan. grep -rbekerja jauh lebih cepat - satu-satunya salinan yang melakukan traversal direktori.
mvp
Benar; meskipun find dapat dikustomisasi untuk hanya beroperasi pada hasil yang difilter, yang kemudian dapat membuat operasi lebih cepat daripada tangkapan semua tangkapan. Tergantung pada konteksnya.
Yam Marcovic