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 '^user1@example.com' text_file

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


1
Apakah email itu satu-satunya kata dalam satu baris?
glenn jackman

memang: file memiliki format ini: user1@example.com 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

Jawaban:


24

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

grep -Fx user1@example.com 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 user1@example.com 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' user1@example.com | 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

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{user1@example.com}' your_file

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.


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 ^user1@example.com, termasuk alamat email itu sendiri, tetapi juga user1@example.com.spammer.com. 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 ')


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 
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.