Encontre a string exata com grep


9

a título de exemplo, eu tenho um grande arquivo de texto com muitos endereços de email, usando o bash, preciso pesquisar / verificar se existe um email (ou não). Deve usar (apenas) as "âncoras"?

grep '^user1@example.com' text_file

ou há maneiras melhores? Preciso criar um script bash e gostaria de estar seguro.


1
O e-mail é a única palavra em uma linha?
Glenn Jackman

de fato: o arquivo tem este formato: user1@example.com example.com/user1
Pol Hallen

1
Nesse caso, eu usaria grep -q '^user1@example\.com\>'- com uma âncora de linha no início e uma âncora de fim de palavra no final.
Glenn Jackman

Respostas:


24

Veja as opções -F(sequência fixa, em oposição à expressão regular) e -x(exata: coincide com a linha inteira).

grep -Fx user1@example.com text_file

seria o equivalente a:

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

(lembre-se de que .é um operador de expressão regular que corresponde a qualquer caractere).

Use a -qopção se você quiser apenas verificar se existe essa linha:

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

Se a linha a pesquisar e o nome do arquivo forem variáveis:

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

Ou

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

Você não quer:

grep -Fxq "$email" "$file"

pois isso causaria problemas se $emailou $fileiniciado -.

Se o arquivo estiver classificado (no seu local atual, preferencialmente C), você poderá acelerar as coisas usando, em commvez de grep:

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

A vantagem se tornará mais óbvia quando você tiver vários endereços de email para verificar (por exemplo, em outro arquivo classificado):

comm -12 text_file emails_to_check

seria mais rápido que:

grep -Fxf emails_to_check text_file

AFAIK, grep -Fxq -- "$email" "$file"também funciona.
vinc17

stephane, por que você mudou de uma entrada de arquivo (manipulada pelo grep) para stdin usando o <redirecionador? existem vantagens?
trema

@ umläute e vinc17. Como eu disse, é para cobrir nomes de arquivos começando com -. ainda grep -- "$email" "$file"seria um problema para um arquivo chamado -(que greptrata especialmente como significado stdin )
Stéphane Chazelas

6

Para ser o mais eficiente possível, você deseja parar depois que a primeira correspondência for encontrada. Se você possui o GNU grep, pode fazer o seguinte:

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

Caso contrário, você pode usar Perl:

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

4
-mé específico do GNU. Use o POSIX -qse quiser verificar eficientemente se existe uma linha assim.
Stéphane Chazelas

3

Existem muitas verificações por email lá. Um deles é:

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

Para elaborar minha resposta.

Você está usando a ^âncora que indica o início da string. Isso não corresponderá se um endereço de email estiver em algum lugar entre uma string longa.


2
Obrigado. Essa é uma opção genérica de grep para "extrair" todos os endereços de email dentro de um arquivo. Preciso procurar um endereço de e-mail um por um usando read EMAIL e depois grep para verificá-lo.
Pol Hallen

2

seu grepcomando corresponderá a tudo o que começar ^user1@example.com, incluindo o próprio endereço de email, mas também user1@example.com.spammer.com. como .é um caractere especial em expressões regulares que corresponde a qualquer tecla, você deve evitá-lo como\.

assumindo que seu arquivo de texto contenha um endereço por linha, use:

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

o final $garantirá que a linha termine após o endereço de email. Também estou usando aspas duplas ", pois elas permitem o uso de variáveis ​​(ao contrário das aspas simples ')


1
Isso também combina user1@example-com.
Stéphane Chazelas

@ StéphaneChazelas, é claro que você está certo; atualizou a resposta.
trema

@ umläute Você precisa dobrar a barra invertida. Mas é melhor usar -Fx.
vinc17

@ vinc17, doh; escape de festança; de qualquer forma, sim, eu concordo que é melhor para uso -Fx, mas isso é de Stephane resposta :-)
trema

0

Considerando correspondência literal / exata geral de seqüência de caracteres:

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

#\b shows boundaries over here.

ou,

 grep  "\bsearch_word\b"  <file>  >  output.txt 
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.