GNU/Linux >> LINUX-Kenntnisse >  >> Ubuntu

Wie kann man eine Reihe von Grep-Anweisungen zu einer Grep-Anweisung kombinieren?

Ich würde gerne wissen, ob es eine Möglichkeit gibt, eine Reihe von grep-Anweisungen zu kombinieren, bei denen der Effekt darin besteht, die Ausdrücke „und“ statt „oder“ die übereinstimmenden Ausdrücke zu verwenden.

Demo unten:

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

Hören Sie sich das Skript an.

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

Akzeptierte Antwort:

Sie können den Filter grep a | grep c | grep -v d zu einem einzigen einfachen grep . Es gibt nur komplizierte und uneffektive Wege. Das Ergebnis hat eine langsame Leistung und die Bedeutung des Ausdrucks ist verschleiert.

Einzelne Befehlskombination der drei Greps

Wenn Sie nur einen einzelnen Befehl ausführen möchten, können Sie awk verwenden das auch mit regulären Ausdrücken funktioniert und diese mit logischen Operatoren kombinieren kann. Hier ist das Äquivalent Ihres Filters:

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

Ich denke, in den meisten Fällen gibt es keinen Grund, eine Pipe zu einem einzelnen Befehl zu vereinfachen, außer wenn die Kombination zu einem relativ einfachen grep-Ausdruck führt, der schneller sein könnte (siehe Ergebnisse unten).

Unix-ähnliche Systeme sind darauf ausgelegt, Pipes zu verwenden und verschiedene Dienstprogramme miteinander zu verbinden. Die Rohrkommunikation ist zwar nicht die effektivste, aber in den meisten Fällen ausreichend. Da heutzutage die meisten neuen Computer mehrere CPU-Kerne haben, können Sie die CPU-Parallelisierung „natürlich“ nutzen, indem Sie einfach eine Pipe verwenden!

Ihr ursprünglicher Filter funktioniert sehr gut und ich denke, dass in vielen Fällen der awk Lösung wäre selbst auf einem einzelnen Kern etwas langsamer.

Leistungsvergleich

Mit einem einfachen Programm habe ich aus den Zeichen a eine zufällige Testdatei mit 200 000 000 Zeilen zu je 4 Zeichen als Zufallskombination generiert , b , c und d . Die Datei hat 1 GB. Während der Tests wurde es vollständig in den Cache geladen, sodass keine Festplattenoperationen die Leistungsmessung beeinflussten. Die Tests wurden auf Intel Dual Core ausgeführt.

Single grep

$ 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

Single awk

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

Die ursprünglichen drei Greps wurden geleitet

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

Hybrid – positive Greps kombiniert, negative Pipe

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

Hier sehen Sie, dass das einzelne grep ist aufgrund des komplexen Ausdrucks sehr langsam. Die ursprüngliche Pipe von drei greps ist wegen einer guten Parallelisierung ziemlich schnell. Ohne Parallelisierung – auf einem einzelnen Kern – läuft die ursprüngliche Pipe nur geringfügig schneller als awk der als einzelner Prozess nicht parallelisiert wird. Awk und grep verwenden wahrscheinlich denselben Code für reguläre Ausdrücke und die Logik der beiden Lösungen ist ähnlich.

Verwandte:Wie viele Jahre wird 11.10 unterstützt?

Der klare Gewinner ist die Hybrierung, die zwei positive Greps kombiniert und das negative in der Pfeife lässt. Es scheint, dass der reguläre Ausdruck mit | hat keine Leistungseinbußen.


Ubuntu
  1. Wie bewegt man sich ein Verzeichnis nach unten?

  2. Wie melde ich mich beim Lxc-Container an?

  3. Wie kann ich in einer Datei nach einem mehrzeiligen Muster suchen?

  4. Wie füge ich zwei statische Bibliotheken zu einer zusammen?

  5. Wie verkettet man mehrere Ausgabezeilen zu einer Zeile?

So schließen Sie den Grep-Befehl unter Linux aus

So verbinden Sie mehrere Zeilen in einer Datei in Linux zu einer

So führen Sie unter Linux mehrere PDF-Dateien zu einem PDF zusammen

So installieren Sie SpiderOak One unter Ubuntu 16.04 und Ubuntu 17.04

Wie teilt man eine MP3-Datei?

Wie füge ich mehrere cPanel-Konten zu einem zusammen?