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.


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


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í.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.