Trouvez la chaîne exacte avec grep

9

à titre d'exemple, j'ai un gros fichier texte avec de nombreuses adresses email, en utilisant bash j'ai besoin de rechercher / vérifier qu'un email existe (ou pas). Doit-on utiliser (uniquement) les "ancres"?

grep '^[email protected]' text_file

ou il y a de meilleures façons? J'ai besoin de créer un script bash et j'aimerais être en sécurité.

Pol Hallen
la source
1
L'e-mail est-il le seul mot sur une ligne?
glenn jackman
en effet: le fichier a ce format: [email protected] example.com/user1
Pol Hallen
1
Dans ce cas, j'utiliserais grep -q '^user1@example\.com\>'- avec une ancre de ligne au début et une ancre de fin de mot à la fin.
glenn jackman
stackoverflow.com/questions/4709912/how-to-grep-the-exact-match
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Réponses:

24

Voir les options -F(chaîne fixe, par opposition à l'expression régulière) et -x(exacte: correspondre à toute la ligne).

grep -Fx [email protected] text_file

serait l'équivalent de:

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

(rappelez-vous que .c'est un opérateur d'expression régulière qui correspond à n'importe quel caractère).

Utilisez l' -qoption si vous souhaitez uniquement vérifier s'il existe une telle ligne:

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

Si la ligne à rechercher et le nom de fichier sont variables:

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

Ou

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

Tu ne veux pas:

grep -Fxq "$email" "$file"

car cela causerait des problèmes si $emailou au $filedébut -.

Si le fichier est trié (dans vos paramètres régionaux actuels, de préférence C), vous pouvez éventuellement accélérer les choses en utilisant commau lieu de grep:

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

L'avantage deviendra plus évident lorsque vous aurez plusieurs adresses e-mail à vérifier (par exemple dans un autre fichier trié):

comm -12 text_file emails_to_check

serait plus rapide que:

grep -Fxf emails_to_check text_file
Stéphane Chazelas
la source
AFAIK, grep -Fxq -- "$email" "$file"fonctionne également.
vinc17
stephane, pourquoi êtes-vous passé d'une entrée de fichier (gérée par grep) à stdin à l'aide du <redirecteur? y a-t-il des avantages?
umläute
@ umläute et vinc17. Comme je l'ai dit, c'est pour couvrir les noms de fichiers commençant par -. même grep -- "$email" "$file"serait un problème pour un fichier appelé -(qui greptraite spécialement comme signifiant stdin )
Stéphane Chazelas
6

Pour être aussi efficace que possible, vous voulez vous arrêter après avoir trouvé la première correspondance. Si vous avez GNU grep, vous pouvez le faire:

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

Sinon, vous pouvez utiliser Perl:

perl -nlE 'say and last if $_ eq q{[email protected]}' your_file
Joseph R.
la source
4
-mest spécifique à GNU. Utilisez le POSIX -qsi vous souhaitez vérifier efficacement qu'il existe une telle ligne.
Stéphane Chazelas
3

Il y a beaucoup de vérifications par e-mail là-bas. L'un d'eux est:

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

Pour élaborer ma réponse.

Vous utilisez l' ^ancre qui indique le début de la chaîne. Cela ne correspondra pas si une adresse e-mail se situe quelque part entre une longue chaîne.

Valentin Bajrami
la source
2
Merci. C'est une option générique de grep pour "extraire" toutes les adresses e-mail dans un fichier. J'ai besoin de rechercher une adresse e-mail une par une en utilisant EMAIL, puis en utilisant grep pour le vérifier.
Pol Hallen
2

votre grepcommande correspondra à tout ce qui commence par ^[email protected], y compris l'adresse e-mail elle-même, mais aussi [email protected]. comme .c'est un caractère spécial dans les expressions régulières qui correspond à n'importe quelle touche, vous devez l'échapper comme\.

en supposant que votre fichier texte contient une adresse par ligne, utilisez:

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

la fin $s'assurera que la ligne se termine après l'adresse e-mail. "j'utilise également des guillemets doubles , car ceux-ci permettent d'utiliser des variables (contrairement aux guillemets simples ')

umläute
la source
1
Cela correspond également user1@example-com.
Stéphane Chazelas
@ StéphaneChazelas vous avez bien sûr raison; mis à jour la réponse.
umläute
@ umläute Vous devez doubler la barre oblique inverse. Mais il vaut mieux l'utiliser -Fx.
vinc17
@ vinc17, doh; bash s'échappant; de toute façon, oui je suis d'accord qu'il vaut mieux l'utiliser -Fxmais c'est la réponse de stephane :-)
umläute
0

Considérant la correspondance générale littérale / chaîne exacte:

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

#\b shows boundaries over here.

ou,

 grep  "\bsearch_word\b"  <file>  >  output.txt 
123Utilisateur
la source