Correspondência negativa usando grep (linhas de correspondência que não contêm foo)


991

Eu tenho tentado elaborar a sintaxe para este comando:

grep ! error_log | find /home/foo/public_html/ -mmin -60

OU:

grep '[^error_log]' | find /home/baumerf/public_html/ -mmin -60

Eu preciso ver todos os arquivos que foram modificados, exceto aqueles nomeados error_log.

Eu li sobre isso aqui , mas só encontrei um notpadrão de regex.


13
[^ error_log] nunca funcionaria de qualquer maneira, [] são classes char, em geral as regexp não são boas em padrões negativos (a menos que o mecanismo implemente lookaheads negativos).
9119 Jaap

Respostas:


1758

grep -v é seu amigo:

grep --help | grep invert  

-v, --invert-match seleciona linhas não correspondentes

Verifique também o relacionado -L(o complemento de -l).

-L, --arquivos sem correspondência apenas imprime nomes de ARQUIVO que não contêm correspondência


125
Vale ressaltar que para várias partidas (negativas) a -eopção pode ser usada:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan

31
Semelhante ao comentário de @ Babken-Vardanyan Também - capaz de usar pipes para participar de várias partidas, por exemplo,grep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams

13
O último comentário NÃO é o mesmo, pois procurará por itens que não coincidem com os dois. ou seja, se ele corresponder a um, mas não ao outro, ainda será impresso. Experimente ambas as maneiras com as cordas não semelhantes
Evan Langlois

7
@EvanLanglois - forçando o grep a interpretar o padrão como uma expressão regular estendida usando -Eworks, ie grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini

1
@ OlleHärstedt, eu acho que eu entendi mal o seu cenário no meu comentário anterior, o seguinte pode ser o que você está procurando grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( por isso o primeiro grep? , Há sempre uma maneira :))
Motti

139

Você também pode usar awkpara esses propósitos, pois permite executar verificações mais complexas de uma maneira mais clara:

Linhas que não contêm foo:

awk '!/foo/'

Linhas que não contêm foonem bar:

awk '!/foo/ && !/bar/'

Linhas que não contêm foonem barque contêm foo2ou bar2:

awk '!/foo/ && !/bar/ && (/foo2/ || /bar2/)'

E assim por diante.


2
Isso é realmente muito legal. Você nem precisa aprender a linguagem awk completa para agrupar a regexp com operadores lógicos. Obrigado por esta resposta!
Peter T.

1
Exatamente o que eu estava procurando, muito obrigado.
precisa

13

No seu caso, você provavelmente não deseja usar grep, mas adicione uma cláusula negativa ao comando find, por exemplo

find /home/baumerf/public_html/ -mmin -60 -not -name error_log

Se você deseja incluir caracteres curinga no nome, precisará escapar deles, por exemplo, para excluir arquivos com o sufixo .log:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
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.