GNU/Linux >> Linux Esercitazione >  >> Ubuntu

Come si può combinare una serie di dichiarazioni Grep convogliate insieme in un'unica dichiarazione Grep?

Vorrei sapere se esiste un modo per combinare una serie di istruzioni grep in cui l'effetto è "e" le espressioni piuttosto che "o" le espressioni corrispondenti.

Demo qui sotto:

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

Ascolta è uno sguardo alla sceneggiatura.

 #!/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"

Risposta accettata:

Non puoi trasformare il filtro grep a | grep c | grep -v d a un singolo semplice grep . Ci sono solo modi complicati e inefficaci. Il risultato ha prestazioni lente e il significato dell'espressione è oscurato.

Combinazione di comando singolo dei tre greps

Se vuoi eseguire un solo comando puoi usare awk che funziona anche con le espressioni regolari e può combinarle con operatori logici. Ecco l'equivalente del tuo filtro:

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

Penso che nella maggior parte dei casi non ci sia motivo per semplificare una pipe in un singolo comando tranne quando la combinazione risulta in un'espressione grep relativamente semplice che potrebbe essere più veloce (vedi risultati sotto).

I sistemi simili a Unix sono progettati per utilizzare tubi e per collegare tra loro varie utenze. Sebbene la comunicazione tramite pipe non sia la più efficace possibile, nella maggior parte dei casi è sufficiente. Poiché al giorno d'oggi la maggior parte dei nuovi computer ha più core CPU, puoi utilizzare "naturalmente" la parallelizzazione della CPU semplicemente usando una pipe!

Il tuo filtro originale funziona molto bene e penso che in molti casi il awk la soluzione sarebbe un po' più lenta anche su un singolo core.

Confronto delle prestazioni

Utilizzando un semplice programma ho generato un file di test casuale con 200 000 000 righe, ciascuna con 4 caratteri come combinazione casuale dai caratteri a , b , c e d . Il file ha 1 GB. Durante i test è stato completamente caricato nella cache, quindi nessuna operazione sul disco ha influito sulla misurazione delle prestazioni. I test sono stati eseguiti su Intel dual core.

Grep singolo

$ 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

Singolo awk

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

I tre grep originali convogliati

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

Ibrido:greps positivi combinati, convogliamento negativo

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

Qui vedi che il singolo grep è molto lento a causa dell'espressione complessa. La pipe originale di tre greps è piuttosto veloce grazie a una buona parallelizzazione. Senza parallelizzazione, su un singolo core, la pipe originale funziona leggermente più veloce di awk che come un singolo processo non è parallelizzato. Awk e grep probabilmente utilizzano lo stesso codice delle espressioni regolari e la logica delle due soluzioni è simile.

Correlati:per quanti anni è supportato l'11.10?

Il chiaro vincitore è l'hybring che combina due grep positivi e lascia quello negativo nella pipe. Sembra che l'espressione regolare con | non ha alcuna penalità di prestazione.


Ubuntu
  1. Come posso cercare uno schema multilinea in un file?

  2. Come posso usare grep per mostrare solo i nomi dei file su Linux?

  3. Come concatenare più righe di output in una riga?

  4. Come gzippare più file in un unico file gz?

  5. Combina più comandi unix in un unico output

Come escludere in Grep Command in Linux

Come unire più righe in una in un file in Linux

Come unire più file PDF in un unico PDF in Linux

Come installare SpiderOak One su Ubuntu 16.04 e Ubuntu 17.04

Come dividere un file Mp3?

Come unire più account cPanel in uno solo