Como fazer grep corresponder apenas se toda a linha corresponder?


104

Eu tenho estes:

$ cat a.tmp
ABB.log
ABB.log.122
ABB.log.123

Eu queria encontrar uma correspondência exata de ABB.log.

Mas quando eu fiz

$ grep -w ABB.log a.tmp
ABB.log
ABB.log.122
ABB.log.123

mostra todos eles.

Posso obter o que desejo usando o grep?

Respostas:


105

Simplesmente especifique as âncoras regexp.

grep '^ABB\.log$' a.tmp

2
Ambas as âncoras (^ e $) são necessárias.
user562374

2
Agradável! E se eu estiver usando o regex para a correspondência de um arquivo? "padrões grep -f a.tmp" ??
green69

@ green69 Vários anos atrasado, mas você pode usar o sed para adicionar as âncoras antes de passar os padrões para o grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Randoms

155
grep -Fx ABB.log a.tmp

Na página de manual do grep:

-F, --fixed-strings
Interpretar PATTERN como uma (lista de) strings fixas
-x, --line-regexp
Seleciona apenas as correspondências que correspondem exatamente a toda a linha.


2
não foi capaz de usar -F, infelizmente.
Johnyy

@Johnyy Não -F? você está no Solaris? Se assim for, use/usr/xpg4/bin/grep
Scrutinizer

9
Estou usando grepdentro de um script bash e esta opção é melhor do que usar uma expressão regular, conforme sugerido na resposta aceita. Porque eu tenho algum caractere especial dentro da variável que estou procurando (como .) e não preciso escapar deles ao usar o comando.
Gustavo Straube

1
melhor resposta IMO porque permite caracteres especiais sem escape
ReneGAED

1
Isso é melhor porque também funciona com variáveis.
ybenjira

23

Aqui está o que eu faço, embora usar âncoras seja a melhor maneira:

grep -w "ABB.log " a.tmp

Como este .. ele retornará a correspondência de primeira linha
user765443

1
Isso requer um espaço depois ABB.log, o que não é o caso geral, ou seja, ele falhará na maioria das vezes.
Jahid

3

A maioria das sugestões falhará se houver um único espaço inicial ou final, o que faria diferença se o arquivo estivesse sendo editado manualmente. Isso o tornaria menos suscetível nesse caso:

grep '^[[:blank:]]*ABB\.log[[:blank:]]*$' a.tmp

Um simples loop while-read no shell faria isso implicitamente:

while read file
do 
  case $file in
    (ABB.log) printf "%s\n" "$file"
  esac
done < a.tmp


1

Pretendo acrescentar algumas explicações extras sobre as tentativas de OP e outras respostas também.

Você também pode usar a solução de John Kugelmans assim:

grep -x "ABB\.log" a.tmp

citar a string e escapar do ponto ( .) faz com que ele não precise mais do -Fsinalizador.

Você precisa escapar do .(ponto) (porque ele corresponde a qualquer caractere (não apenas .) se não for escapado) ou usar a opção -Fcom grep. -Fsinalizador torna uma string fixa (não um regex).

Se você não citar a string, pode ser necessário barra invertida dupla para escapar do ponto ( .):

grep -x ABB\\.log a.tmp


Teste:

$ echo "ABBElog"|grep -x  ABB.log
ABBElog #matched !!!
$ echo "ABBElog"|grep -x  "ABB\.log"
#returns empty string, no match


Nota:

  1. -x forças para corresponder a toda a linha.
  2. Respostas que usam um sinalizador .sem escape -Festão erradas
  3. Você pode evitar a -xtroca envolvendo sua string de padrão com ^e $. Neste caso, certifique-se de não usar -F, em vez de escapar de ., porque -Fimpedirá a interpretação de regex de ^e $.


EDITAR: (Adicionando explicação extra em relação a @hakre):

Se você deseja combinar uma string começando com -, então você deve usar --com grep. O que vier a seguir --será considerado uma entrada (não uma opção).

Exemplo:

echo -f |grep -- "-f"     # where grep "-f" will show error
echo -f |grep -F -- "-f"  # whre grep -F "-f" will show error
grep "pat" -- "-file"     # grep "pat" "-file" won't work. -file is the filename

Você realmente sentiu que -F estava faltando no seu caso? Em caso afirmativo, você pode dizer qual foi o caso?
hakre

@hakre Você leu minha resposta completamente? Expliquei (muito claramente) por -Fque não será necessário se o .for escapado corretamente.
Jahid

Certo. Claro, só estou perguntando: estava -Fdisponível quando você escreveu isso? Se não, qual sistema você estava usando? Não consegui encontrar essa informação em sua resposta até agora, o que até agora acontece quando eu a reli novamente. Com certeza, li sua resposta completamente pelo menos duas vezes. ;)
hakre

@hakre Claro que -Festava disponível. (Eu disse: "ou usar -Fsinalizar com grep")
Jahid

Obrigado pelo insight. Resta apenas uma pequena pergunta: se -Ffor a resposta, por que se preocupar em fugir? Qual sua opinião sobre isso?
hakre

1

Isso funcionou bem para mim ao tentar fazer algo semelhante:

grep -F ABB.log a.tmp

-1
    $ cat venky
    ABB.log
    ABB.log.122
    ABB.log.123

    $ cat venky | grep "ABB.log" | grep -v "ABB.log\."
    ABB.log
    $

    $ cat venky | grep "ABB.log.122" | grep -v "ABB.log.122\."
    ABB.log.122
    $

1
Isso também corresponderá aos arquivos que terminam com ABB.log e os pontos devem ser escapados.
Escrutinador de

-1

Funciona para mim :

grep "\bsearch_word\b" text_file > output.txt  

\b indica / define limites.

Parece funcionar muito rápido


Isso também corresponde a qualquer linha que contenha search_wordseparados por limites de palavras. Por exemplo, ele corresponderia à linha, "foo search_word bar".
Rohan Singh

-2

Isso é com HPUX, se o conteúdo dos arquivos tiver espaço entre palavras, use isto:

egrep "[[:space:]]ABC\.log[[:space:]]" a.tmp


O OP queria corresponder a toda a linha, não uma palavra delimitada por espaço dentro da linha.
Keith Thompson


-3

Eu precisava desse recurso, mas também queria ter certeza de não retornar linhas com um prefixo antes de ABB.log:

  • ABB.log
  • ABB.log.122
  • ABB.log.123
  • 123ABB.log

grep "\WABB.log$" -w a.tmp

Isso só corresponderá se o líder \Wfor satisfeito, que é qualquer caractere sem espaço em branco, portanto xABBxlog.
bschlueter
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.