Trova la stringa esatta con grep


9

a titolo di esempio, ho un grande file di testo con molti indirizzi e-mail, usando bash ho bisogno di cercare / verificare l'esistenza di una e-mail (o no). Dovrebbero essere utilizzati (solo) gli "ancoraggi"?

grep '^user1@example.com' text_file

o ci sono modi migliori? Ho bisogno di creare uno script bash e vorrei essere al sicuro.


1
L'e-mail è l'unica parola su una riga?
Glenn Jackman,

infatti: il file ha questo formato: user1@example.com example.com/user1
Pol Hallen

1
In quel caso, userei grep -q '^user1@example\.com\>'- con un'ancora di linea all'inizio e un'ancora di fine parola alla fine.
Glenn Jackman,

Risposte:


24

Vedi le opzioni -F(stringa fissa, anziché espressione regolare) e -x(esatto: abbina l'intera riga).

grep -Fx user1@example.com text_file

sarebbe l'equivalente di:

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

(ricorda che si .tratta di un operatore di espressioni regolari che corrisponde a qualsiasi carattere).

Utilizzare l' -qopzione se si desidera solo verificare se esiste una tale linea:

grep -Fxq user1@example.com text_file &&
  echo yes, that address is in that file.

Se la riga da cercare e il nome del file sono variabili:

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

O

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

Non vuoi:

grep -Fxq "$email" "$file"

in quanto ciò causerebbe problemi se $emailo $fileiniziato con -.

Se il file è ordinato (preferibilmente nella tua lingua corrente C), puoi accelerare le cose usando comminvece di grep:

printf '%s\n' user1@example.com | comm -12 - text_file

Il vantaggio diventerà più evidente quando si hanno più indirizzi e-mail da controllare (ad esempio in un altro file ordinato):

comm -12 text_file emails_to_check

sarebbe più veloce di:

grep -Fxf emails_to_check text_file

AFAIK, grep -Fxq -- "$email" "$file"funziona anche.
vinc17,

stephane, perché sei passato da un input di file (gestito da grep) a stdin usando il <redirector? ci sono dei vantaggi?
umläute,

@ umläute e vinc17. Come ho detto, è per coprire i nomi dei file a partire da -. grep -- "$email" "$file"sarebbe anche un problema per un file chiamato -(che greptratta specialmente come significato stdin )
Stéphane Chazelas

6

Per essere il più efficiente possibile, vuoi fermarti dopo aver trovato la prima partita. Se hai GNU grep, puoi farlo:

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

In caso contrario, è possibile utilizzare Perl:

perl -nlE 'say and last if $_ eq q{user1@example.com}' your_file

4
-mè specifico per GNU. Utilizzare POSIX -qse si desidera verificare in modo efficiente l'esistenza di tale linea.
Stéphane Chazelas,

3

Ci sono molti controlli e-mail lì. Uno di questi è:

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

Per elaborare la mia risposta.

Stai usando l' ^ancoraggio che indica l'inizio della stringa. Questo non corrisponderà se un indirizzo e-mail si trova tra una stringa lunga.


2
Grazie. Questa è un'opzione grep generica per "estrarre" tutti gli indirizzi email all'interno di un file. Ho bisogno di cercare uno per uno indirizzo e-mail usando read EMAIL quindi usando grep per verificarlo.
Pol Hallen,

2

il tuo grepcomando corrisponderà a tutto ciò che inizia ^user1@example.com, incluso l'indirizzo email stesso, ma anche user1@example.com.spammer.com. poiché .è un carattere speciale nelle espressioni regolari che corrisponde a qualsiasi tasto, dovresti evitarlo come\.

supponendo che il tuo file di testo contenga un indirizzo per riga, usa:

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

il trailing $farà in modo che la riga termini dopo l'indirizzo e-mail. sto anche usando le virgolette doppie ", in quanto consentono di utilizzare le variabili (a differenza delle virgolette singole ')


1
Anche questo corrisponde user1@example-com.
Stéphane Chazelas,

@ StéphaneChazelas hai ovviamente ragione; aggiornata la risposta.
umläute,

@ umläute È necessario raddoppiare la barra rovesciata. Ma è meglio usare -Fx.
vinc17,

@ vinc17, doh; bash in fuga; in ogni caso, sì, sono d'accordo che è meglio usare, -Fxma questa è la risposta di
Stephane

0

Considerando la corrispondenza di stringa generale / esatta:

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

#\b shows boundaries over here.

o,

 grep  "\bsearch_word\b"  <file>  >  output.txt 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.