Coincidencia negativa con grep (líneas de coincidencia que no contienen foo)

991

He estado tratando de resolver la sintaxis de este comando:

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

O:

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

Necesito ver todos los archivos que han sido modificados, excepto los nombrados error_log.

He leído sobre esto aquí , pero solo encontré un notpatrón de expresiones regulares.

jerrygarciuh
fuente
13
[^ error_log] nunca funcionaría de todos modos, [] son ​​clases char, las expresiones regulares en general no son buenas en patrones negativos (a menos que el motor implemente lookaheads negativos).
Jaap

Respuestas:

1758

grep -v es tu amigo:

grep --help | grep invert  

-v, --invert-match selecciona líneas no coincidentes

También echa un vistazo a lo relacionado -L(el complemento de -l).

-L, --files-sin coincidencia solo imprime nombres de ARCHIVO que no contienen coincidencia

Motti
fuente
125
Vale la pena mencionar que para múltiples partidos (negativos) -ese puede usar la opción:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan
31
Similar al comentario de @ Babken-Vardanyan También - capaz de usar tuberías para unir múltiples partidos, por ejemplogrep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams
13
El último comentario NO es lo mismo, ya que buscará cosas que no coincidan con ambas en lugar de con ninguna. es decir, si coincide con uno pero no con el otro, todavía está impreso. Pruébelo en ambos sentidos con cadenas no similares
Evan Langlois
77
@EvanLanglois - obligando a grep a interpretar el patrón como una expresión regular extendida usando -Etrabajos, es decir grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini
1
@ OlleHärstedt, creo que entendí mal su escenario en mi comentario anterior, lo siguiente puede ser lo que está buscando grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( ¿ por qué el primer grep?, Siempre hay una manera :))
Motti
139

También puede usar awkpara estos fines, ya que le permite realizar verificaciones más complejas de una manera más clara:

Líneas que no contienen foo:

awk '!/foo/'

Líneas que no contienen fooni bar:

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

Líneas que no contienen ni footampoco barque contienen ya sea foo2o bar2:

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

Y así.

fedorqui 'así que deja de dañar'
fuente
2
Eso es realmente genial. Ni siquiera tiene que aprender el lenguaje awk completo para agrupar expresiones regulares con operadores lógicos. Gracias por esta respuesta!
Peter T.
1
Exactamente lo que estaba buscando, muchas gracias.
mmrs151
13

En su caso, presumiblemente no desea usar grep, sino que agrega una cláusula negativa al comando find, por ejemplo

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

Si desea incluir comodines en el nombre, deberá escapar de ellos, por ejemplo, para excluir archivos con sufijo .log:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
papá Pitufo
fuente