Temukan string yang tepat dengan grep

9

Sebagai contoh, saya memiliki file teks besar dengan banyak alamat email, menggunakan bash Saya perlu mencari / memverifikasi bahwa ada email (atau tidak ada). Haruskah menggunakan (hanya) "jangkar"?

grep '^[email protected]' text_file

atau ada cara yang lebih baik? Saya perlu membuat skrip bash dan saya ingin aman.

Pol Hallen
sumber
1
Apakah email itu satu-satunya kata dalam satu baris?
glenn jackman
memang: file memiliki format ini: [email protected] example.com/user1
Pol Hallen
1
Dalam hal ini, saya akan menggunakan grep -q '^user1@example\.com\>'- dengan jangkar garis di awal, dan jangkar akhir kata di akhir.
glenn jackman
stackoverflow.com/questions/4709912/how-to-grep-the-exact-match
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Jawaban:

24

Lihat opsi -F(string tetap, yang bertentangan dengan ekspresi reguler) dan -x(tepat: cocokkan dengan seluruh baris).

grep -Fx [email protected] text_file

akan sama dengan:

grep '^user1@example\.com$' text_file

(ingat itu .adalah operator ekspresi reguler yang cocok dengan karakter apa pun).

Gunakan -qopsi jika Anda hanya ingin memeriksa apakah ada garis seperti itu:

grep -Fxq [email protected] text_file &&
  echo yes, that address is in that file.

Jika baris yang dicari dan nama file variabel:

grep -Fxqe "$email" < "$file"

Atau

grep -Fxq -- "$email" < "$file"

Anda tidak mau:

grep -Fxq "$email" "$file"

karena itu akan menimbulkan masalah jika $emailatau $filedimulai dengan -.

Jika file diurutkan (di tempat Anda saat ini, lebih disukai C), Anda mungkin dapat mempercepat dengan menggunakan commalih-alih grep:

printf '%s\n' [email protected] | comm -12 - text_file

Keuntungan akan menjadi lebih jelas ketika Anda memiliki beberapa alamat email untuk diperiksa (misalnya dalam file yang diurutkan lainnya):

comm -12 text_file emails_to_check

akan lebih cepat dari:

grep -Fxf emails_to_check text_file
Stéphane Chazelas
sumber
AFAIK, grep -Fxq -- "$email" "$file"juga berfungsi.
vinc17
stephane, mengapa Anda beralih dari input file (ditangani oleh grep) ke stdin menggunakan <redirector? apakah ada keuntungan?
umläute
@ umläute dan vinc17. Seperti yang saya katakan, itu untuk menutupi nama file dimulai dengan -. bahkan grep -- "$email" "$file"akan menjadi masalah untuk file bernama -(yang grepmemperlakukan secara khusus sebagai makna stdin )
Stéphane Chazelas
6

Agar seefisien mungkin, Anda ingin berhenti setelah kecocokan pertama ditemukan. Jika Anda memiliki GNU grep, Anda dapat melakukan ini:

grep -m 1 '^user1@example\.com$' your_file

Jika tidak, Anda dapat menggunakan Perl:

perl -nlE 'say and last if $_ eq q{[email protected]}' your_file
Joseph R.
sumber
4
-mkhusus untuk GNU. Gunakan POSIX -qjika Anda ingin memeriksa secara efisien bahwa ada garis seperti itu.
Stéphane Chazelas
3

Ada banyak cek email di sana. Salah satunya adalah:

grep -E -o "\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b" text_file

Untuk menguraikan jawaban saya.

Anda menggunakan ^jangkar yang menunjukkan awal dari string. Ini tidak akan cocok jika alamat email berada di antara string panjang.

Valentin Bajrami
sumber
2
Terima kasih. Itu adalah opsi grep umum untuk "mengekstrak" semua alamat email di dalam file. Saya perlu mencari satu per satu alamat email menggunakan read EMAIL kemudian menggunakan grep untuk memeriksanya.
Pol Hallen
2

grepperintah Anda akan cocok dengan semua yang dimulai dengan ^[email protected], termasuk alamat email itu sendiri, tetapi juga [email protected]. karena .merupakan karakter khusus dalam ekspresi reguler yang cocok dengan tombol apa pun, Anda harus menghindarinya\.

dengan asumsi bahwa file teks Anda mengandung satu alamat per baris, gunakan:

EMAIL=user1@example\\.com
egrep "^${EMAIL}$" text_file

trailing $akan memastikan bahwa sambungan berakhir setelah alamat email. Saya juga menggunakan tanda kutip ganda ", karena ini memungkinkan untuk menggunakan variabel (tidak seperti tanda kutip tunggal ')

umläute
sumber
1
Itu juga cocok user1@example-com.
Stéphane Chazelas
@ StéphaneChazelas Anda tentu saja benar; memperbarui jawabannya.
umläute
@ umläute Anda harus menggandakan backslash. Tapi lebih baik digunakan -Fx.
vinc17
@ vinc17, doh; bash melarikan diri; Bagaimanapun, ya saya setuju bahwa itu lebih baik untuk digunakan -Fxtapi itu jawaban stephane :-)
umläute
0

Mempertimbangkan kecocokan string harfiah / umum:

grep -w "search_word" <file>  >  output.txt

#\b shows boundaries over here.

atau,

 grep  "\bsearch_word\b"  <file>  >  output.txt 
123 Pengguna
sumber