GNU/Linux >> Tutoriales Linux >  >> Ubuntu

¿Cómo se puede combinar una serie de sentencias Grep conectadas en una sola sentencia Grep?

Me gustaría saber si hay una manera de combinar una serie de declaraciones grep donde el efecto es "y" las expresiones en lugar de "o" las expresiones coincidentes.

Demostración a continuación:

./script  
     From one grep statement, I want output like this
a b c

     not like this
a
c
a b
a b c
a b c d

Hear es un vistazo al guión.

 #!/bin/bash
 string="a
 b
 c
 d
 a b
 a b c
 a b c d"

 echo -e "\t From one grep statement I want output like this"
 echo "$string" |
 grep a |grep c |grep -v d #Correct output but pipes three grep statements

 echo -e "\n\tNot like this"
 echo "$string" |
 grep -e'a' -e'c' -e-v'd' #One grep statement but matching expressions are "or" versus "and"

Respuesta aceptada:

No puede transformar el filtro grep a | grep c | grep -v d a un solo grep simple . Solo hay formas complicadas e ineficaces. El resultado tiene un rendimiento lento y el significado de la expresión se oscurece.

Combinación de comando único de los tres greps

Si solo desea ejecutar un solo comando, puede usar awk que también funciona con expresiones regulares y puede combinarlas con operadores lógicos. Este es el equivalente de su filtro:

awk '/a/ && /c/ && $0 !~ /d/'

Creo que, en la mayoría de los casos, no hay razón para simplificar una canalización en un solo comando, excepto cuando la combinación da como resultado una expresión grep relativamente simple que podría ser más rápida (consulte los resultados a continuación).

Los sistemas similares a Unix están diseñados para usar tuberías y conectar varias utilidades entre sí. Aunque la comunicación por tubería no es lo más efectiva posible, en la mayoría de los casos es suficiente. ¡Debido a que hoy en día la mayoría de las computadoras nuevas tienen múltiples núcleos de CPU, puede utilizar "naturalmente" la paralelización de la CPU simplemente usando una tubería!

Tu filtro original funciona muy bien y creo que en muchos casos el awk la solución sería un poco más lenta incluso en un solo núcleo.

Comparación de rendimiento

Usando un programa simple, generé un archivo de prueba aleatorio con 200 000 000 líneas, cada una con 4 caracteres como una combinación aleatoria de los caracteres a , b , c y d . El archivo tiene 1 GB. Durante las pruebas, se cargó por completo en el caché, por lo que ninguna operación del disco afectó la medición del rendimiento. Las pruebas se realizaron en Intel de doble núcleo.

Grep único

$ time ( grep -E '^[^d]*a[^d]*c[^d]*$|^[^d]*c[^d]*a[^d]*$' testfile >/dev/null )
real    3m2.752s
user    3m2.411s
sys 0m0.252s

Awk único

$ time ( awk '/a/ && /c/ && $0 !~ /d/' testfile >/dev/null )
real    0m54.088s
user    0m53.755s
sys 0m0.304s

Los tres greps originales canalizados

$ time ( grep a testfile | grep c | grep -v d >/dev/null )
real    0m28.794s
user    0m52.715s
sys 0m1.072s

Híbrido:greps positivos combinados, canalización negativa

$ time ( grep -E 'a.*c|c.*a' testfile | grep -v d >/dev/null )
real    0m15.838s
user    0m24.998s
sys 0m0.676s

Aquí ves que el único grep es muy lento debido a la expresión compleja. La tubería original de tres greps es bastante rápida debido a una buena paralelización. Sin paralelización, en un solo núcleo, la canalización original se ejecuta un poco más rápido que awk que como un solo proceso no está paralelizado. Awk y grep probablemente usan el mismo código de expresiones regulares y la lógica de las dos soluciones es similar.

Relacionado:¿Cuántos años es compatible con 11.10?

El claro ganador es el híbrido que combina dos greps positivos y deja el negativo en la tubería. Parece que la expresión regular con | no tiene penalización de rendimiento.


Ubuntu
  1. ¿Cómo bajar un directorio?

  2. ¿Cómo fusionar dos bibliotecas estáticas ar en una?

  3. ¿Cómo puedo usar grep para mostrar solo nombres de archivo en Linux?

  4. ¿Cómo concatenar varias líneas de salida en una sola línea?

  5. ¿Cómo gzip varios archivos en un archivo gz?

Cómo excluir en el comando Grep en Linux

Cómo unir varias líneas en una en un archivo en Linux

Cómo combinar varios archivos PDF en un solo PDF en Linux

Cómo instalar SpiderOak One en Ubuntu 16.04 y Ubuntu 17.04

¿Cómo dividir un archivo Mp3?

¿Cómo fusiono varias cuentas de cPanel en una sola?