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.