it-swarm.com.de

grepping mit dem Ergebnis der vorherigen grep

Gibt es eine Möglichkeit, ein Grep basierend auf den Ergebnissen eines vorherigen Grep durchzuführen, anstatt nur mehrere Greps ineinander zu leiten. Angenommen, ich habe die Protokolldatei wie folgt ausgegeben:

ID 1000 xyz occured
ID 1001 misc content
ID 1000 misc content
ID 1000 status code: 26348931276572174
ID 1000 misc content
ID 1001 misc content

Zunächst möchte ich die gesamte Protokolldatei abfragen, um zu sehen, ob "xyz occured" vorhanden ist. Wenn dies der Fall ist, möchte ich die ID-Nummer dieses Ereignisses erhalten und alle Zeilen in der Datei mit dieser ID-Nummer nach dem Statuscode suchen.

Ich hatte mir vorgestellt, dass ich Xargs oder so etwas verwenden könnte, aber ich kann nicht scheinen, dass es funktioniert.

grep "xyz occured" file.log | awk '{ print $2 }' | xargs grep "status code" | awk '{print $NF}'

Irgendwelche Ideen, wie man das eigentlich macht?

14
Chris Robinson

Du bist fast da. Auch wenn xargs manchmal verwendet werden kann, um das zu tun, was Sie wollen (je nachdem, wie der nächste Befehl seine Argumente verwendet), verwenden Sie es eigentlich nicht, um die gerade extrahierte ID zu verwenden. Was Sie tun müssen, ist die Ausgabe des ersten grep (mit dem ID-Code) zu nehmen und dies im nächsten grep-Ausdruck zu verwenden. So etwas wie:

grep "^ID `grep 'xyz occured' file.log | awk '{print $2}'` status code" file.log

Eine andere Möglichkeit wäre natürlich, ein Skript zu schreiben, um dies in einem Durchlauf zu tun, a-la Eds Vorschlag.

6
Andy Ross

Eine allgemeine Antwort zum Begrenzen der Ausgabe in grep-ed: 

grep 'patten1' *.txt | grep 'pattern2' 

beachten Sie, dass der zweite grep nicht auf eine Datei zeigt. 

Mehr über coole Grep-Sachen hier

19
ab-user

Grep das Ergebnis eines vorherigen Grep:

Gegeben dieser Dateiinhalt:

ID 1000 xyz occured
ID 1001 misc content
ID 1000 misc content
ID 1000 status code: 26348931276572174
ID 1000 misc content
ID 1001 misc content

Dieser Befehl:

grep "xyz" file.log | awk '{ print $2 }' > f.log; grep `cat f.log` file.log;

gibt das zurück:

ID 1000 xyz occured
ID 1000 misc content
ID 1000 status code: 26348931276572174
ID 1000 misc content

Es sucht nach "xyz" in file.log und fügt das Ergebnis in f.log ein. Dann greift diese ID in file.log. Wenn das äußere grep mehrere ID-Nummern zurückgibt, sucht das innere grep nur nach der ersten ID-Nummer und den anderen Fehlern.

1
Eric Leschinski

Noch ein anderer Weg

for x in `grep "xyz occured" file.log | cut -d\  -f2`
do
  grep $x file.log
done

Was mir an dieser Methode gefällt, ist, wenn Sie möchten, dass Sie die Ausgabe für jeden Statuscode in eine Datei schreiben.

grep $x file.log >> /var/tmp/$x.out
1
madflojo

Verwenden Sie einfach awk:

awk '{info[$2] = info[$2] $0 ORS} /xyz occured/{ids[$2]} END{ for (id in ids) printf "%s",info[id]}' file.log

oder:

awk '/status code/{code[$2]=$NF} /xyz occured/{ids[$2]} END{ for (id in ids) print code[id]}' file.log

je nachdem, was Sie wirklich ausgeben möchten. Einige erwartete Ausgaben in Ihrer Frage würden helfen.

1
Ed Morton

Hier geht es darum, die Dateien in einem eingegrenzten Suchbereich abzurufen. In Ihrem Fall wird der Suchumfang durch einen Dateiinhalt bestimmt. 

Ich habe dieses Problem häufiger gefunden, während der Suchumfang durch viele Suchvorgänge reduziert wurde (indem Filter auf die vorherigen grep-Ergebnisse angewendet wurden). 

Der Versuch, eine allgemeine Antwort zu finden:

1) Erzeugen Sie eine Liste mit dem Ergebnis des ersten grep:

grep pattern | awk -F':' '{print $1}'

2) Zweites grep in die Liste der Dateien wie hier

xargs grep -i pattern

3) Wenden Sie diesen Kaskadierungsfilter zu den Zeiten an, zu denen Sie lediglich awk hinzufügen müssen, um nur die Dateinamen und xargs an die Dateinamen an grep -i zu übergeben. 

Zum Beispiel:

grep 'pattern1' | awk -F':' '{print $1}' | xargs grep -i 'pattern2'
0
yucer