grep para "término" y excluir "otro término"


28

Estoy tratando de construir una búsqueda grep que busque un término pero excluya líneas que tienen un segundo término. Quería usar varias -e "pattern"opciones, pero eso no funcionó.

Aquí hay un ejemplo de un comando que probé y el mensaje de error que generó.

grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory

Me parece que se -vaplica a todos los términos / patrones de búsqueda. A medida que esto se ejecuta pero luego no se incluye search termen los resultados.

grep -i -E "search term" -ve "exclude term"

¿Hay alguna otra opción para excluir, ya que a veces tenemos que agrupar líneas alrededor de una palabra y si excluimos en la siguiente operación usando '|' , solo elimina esa palabra pero no elimina el bloqueo de esa palabra
— Estudiante

Respuestas:


40

Para y expresiones con grep necesitas dos invocaciones:

grep -Ei "search term" | grep -Eiv "exclude term"

Si los términos que está buscando no son expresiones regulares, utilice la coincidencia de cadena fija ( -F), que es más rápida:

grep -F "search term" | grep -Fv "exclude term"

18

A menos que invoquemos grep dos veces, solo se me ocurre una forma de lograrlo. Involucra expresiones regulares compatibles con Perl (PCRE) y algunas afirmaciones de observación bastante extravagantes .

Para buscar foo excluyendo coincidencias que contengan barra , puede usar:

grep -P '(?=^((?!bar).)*$)foo'

Así es como funciona:

  • (?!bar)coincide con cualquier cosa que no se barra sin consumir caracteres de la cadena. Luego .consume un solo personaje.

  • ^((?!bar).)*repite lo anterior desde el inicio de la cadena ( ^) hasta el final ( $). Fallará si barse encuentra en un punto dado, ya (?!bar)que no coincidirá.

  • (?=^((?!bar).)*$) se asegura de que la cadena coincida con el patrón anterior, sin consumir caracteres de la cadena.

  • foobusca a foo como de costumbre.

¿Encontré este truco en la expresión regular para que coincida con la cadena que no contiene una palabra? . En la respuesta de Bart Kiers , puede encontrar una explicación mucho más detallada de cómo funciona la perspectiva negativa.


Buen truco. Este truco también funciona en Java, por cierto.
— Raman

12

Si desea hacer esto de una sola vez, puede usar awk en lugar de grep.

Formato:

echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'

Ejemplos:

  • echo "hello there" | awk '/hello/ && !/there/'

No devuelve nada

  • echo "hello thre" | awk '/hello/ && !/there/'

Devoluciones: hola thre

  • echo "hllo there" | awk '/hello/ && !/there/'

No devuelve nada

Para múltiples patrones, puede usar paréntesis para agruparlos.

Ejemplos:

  • echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'

Devoluciones: hola thre

  • echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'

Devoluciones: hola tres

  • echo "hello there" | awk '(/hello/ || /hi/) && !/there/'

No devuelve nada

  • echo "hi there" | awk '(/hello/ || /hi/) && !/there/'

No devuelve nada


1
Funcionó para mí, pero perdí los colores = P
— Leopoldo Sanczyk

1
¿Colores de qué salida? Si está tratando de preservar los colores con ls, use el argumento "--color = always" cada vez que analice la salida (o normalmente siempre perderá los colores al analizar el texto). Ejemplo: ls --color=always | awk '/hello/ && !/goodbye/'
— Philip Reese

Gracias por la respuesta @Philip! Lo intenté antes, pero sin éxito. Supongo que como el patrón tiene el texto coloreado, no coincide más tarde, y debería incluir algún tipo de código de color en el patrón. De todos modos, el tuyo es la forma más rápida que encontré grep -Ren varios archivos de código usando la línea de comandos de Ubuntu.
— Leopoldo Sanczyk

1

De mis experimentos no parece que haya mucha diferencia si canaliza sus términos de exclusión a través de grepo sed. Sed tiene algunas otras características útiles de reemplazo de texto que a menudo uso para filtrar mejor la salida de archivos de registro. Así que voy a usar sed ya que combino bastantes filtros en sed.

wc /var/log/tomcat/tomcat.2013-01-14.log.1 
  1851725

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login caducado / d" | baño
24.05 usuario 0.15 sistema 0: 25.27 CPU 95% transcurrida (0avgtext + 0avgdata 3504maxresident) k
0 entradas + 0 salidas (0 mayor + 246 menor) fallas de página 0 intercambios
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login caducado / d" | baño
23.50 usuario 0.16 sistema 0: 24.48 CPU 96% transcurrido (0avgtext + 0avgdata 3504maxresident) k
0 entradas + 0 salidas (0 mayor + 246 menor) fallas de página 0 intercambios
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "iniciar sesión OK" -e "Inicio de sesión caducado" | baño
23.08usuario 0.14sistema 0: 23.55elapsado 98% CPU (0avgtext + 0avgdata 3504maxresident) k
0 entradas + 0 salidas (0 mayor + 246 menor) fallas de página 0 intercambios
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "iniciar sesión OK" -e "Inicio de sesión caducado" | baño
23.50 usuario 0.15 sistema 0: 25.27 transcurrido 93% CPU (0avgtext + 0avgdata 3488maxresident) k
0 entradas + 0 salidas (0 mayor + 245 menor) fallas de página 0 intercambios
   5614 91168 1186298


3
Intente comparar el tiempo de ejecución de en grep -Flugar de grep -Ey no lo use -isi no lo necesita.
— Thor

1
Pero entonces no proporcionas ejemplos usando sed;)
— Benjamin R
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.