2013-05-01 7 views
92

Ich habe eine Reihe von Zeilen aus einer Datei nach dem Ausführen des grep Befehl abgerufen empfangen wie folgt verarbeiten:Wie jede Zeile als Ergebnis der Befehl grep

var=`grep xyz abc.txt` 

Lassen Sie uns sagen, dass ich 10 Zeilen bekam, die von xyz besteht als Ergebnis.

Jetzt muss ich jede Zeile verarbeiten, die ich als Ergebnis des Grep-Befehls erhalten habe. Wie gehe ich hier vor?

+2

Keine der Antworten hier erwähnt die Macht des 'grep -o' für diese Art der Sache. Das '-o'-Flag gibt _only_ den übereinstimmenden Text mit einer Übereinstimmung pro Zeile der Ausgabe zurück.(Es ist nicht erschöpfend, so 'Echo aaa | grep‚a *‘' gibt Ihnen nur „aaa“ und läßt die drei teilweise Übereinstimmungen „“, „a“ und „aa“) –

Antwort

169

Eine der einfachen Möglichkeiten besteht nicht darin, die Ausgabe in einer Variablen zu speichern, sondern direkt mit einer while/read-Schleife darüber zu iterieren.

Etwas wie:

grep xyz abc.txt | while read -r line ; do 
    echo "Processing $line" 
    # your code goes here 
done 

Es gibt Variationen dieses Schema genau je nachdem, was Sie nach.

Wenn Sie Variablen innerhalb der Schleife zu ändern (und haben diese Änderung sichtbar außerhalb davon sein), können Sie die Prozess Substitution verwenden, wie in fedorqui's answer angegeben:

while read -r line ; do 
    echo "Processing $line" 
    # your code goes here 
done < <(grep xyz abc.txt) 
+0

, wenn es keine Zeile mit xyz ist? –

+0

Dann passiert nichts, die Schleife wird nicht ausgeführt. – Mat

+10

Das Problem bei dieser Methode ist, dass (wegen des Rohres) alles innerhalb der Schleife ist in einer Subshell, so Variablen Einstellung außerhalb der Schleife während der Schleife definierte nicht ihre Werte zur Verfügung, nachdem die Schleife machen! –

16

Sie können folgende while read Schleife tun, das wird durch das Ergebnis des grep mit der Befehl so genannte Prozess Substitution zugeführt werden:

while IFS= read -r result 
do 
    #whatever with value $result 
done < <(grep "xyz" abc.txt) 

auf diese Weise haben Sie nicht das Ergebnis in einer variablen zu speichern, sondern direkt „injizieren“ seine Ausgabe an den Schleife.


Beachten Sie die Verwendung von IFS= und read -r entsprechend den Empfehlungen in BashFAQ/001: How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?:

Die Option -r verhindert Backslash Interpretation zu lesen (in der Regel als Backslash Newline Paar verwendet, über mehrere Zeilen oder die Trennzeichen zu entkommen). Ohne diese Option werden alle in der Eingabe nicht enthaltenen Backslashes verworfen. Sie sollten fast immer die Option -r mit lesen verwenden.

Im obigen Szenario verhindert IFS = Trimmen von führenden und hinteren Leerzeichen. Entfernen Sie es, wenn Sie diesen Effekt möchten.

Bezüglich des Verfahrens Substitution, ist es in den bash hackers page erläutert:

Prozess Substitution eine Form der Umleitung ist, wo der Eingang oder Ausgang eines Prozesses (irgendeine Folge von Befehlen) als temporären erscheinen Datei.

+4

Die zweite ist korrekt (obwohl 'read -r' sicherer ist); das erste funktioniert nur mit Whitespace-freien Linien. – chepner

+0

OK, ich habe die 'for' Version durchgestrichen. Versucht eine Schleife auf 'zu tun "$ {$ (grep xyz abc.txt) [@]}"' wie in http://stackoverflow.com/a/14588210/1983854 konnte aber nicht. Ich lasse also die erste Version. – fedorqui

+1

Sie können keine Parameter Expansion auf einen Befehl Substitution anwenden (es sei denn, Sie verwenden 'zsh', wo diese Art von Verschachtelung funktioniert wahrscheinlich). – chepner

5

Ich würde vorschlagen, awk anstelle von grep + etwas anderes hier.

awk '$0~/xyz/{ //your code goes here}' abc.txt

+2

Sogar 'awk '/ xyz /' würde funktionieren. – fedorqui

+0

Wie würden Sie die komplette gefundene Zeile in '// Ihr Code geht hier 'referenzieren? – user857990

+1

@ user857990 Die gesamte Zeile wird in AWK als $ 0 dargestellt. –

Verwandte Themen