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.

jerrygarciuh
fonte
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

Motti
fonte
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.

fedorqui 'Então pare de prejudicar'
fonte
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
Papa Smurf
fonte