Protokolldatei schließen, aber nur bestimmte Zeilen anzeigen

29

Ich verfolge eine Protokolldatei mit dem Flag -f. Dann leite ich dies an grep weiter, um nur Zeilen zu finden, die "X" enthalten. Das funktioniert einwandfrei. Jetzt möchte ich das noch einmal in ein anderes grep leiten, das alle Zeilen entfernt, die "Y" enthalten. Wenn ich die zweite Pipe hinzufüge, wird die Datei nicht mehr aktualisiert und es scheinen keine Daten zu kommen.

Dies ist der Befehl, der funktioniert: tail -f my_file.log | grep "X"

Dies ist der Befehl, der nicht: tail -f my_file.log | grep "X" | grep -v "Y"

Wie soll ich das so strukturieren, dass der Befehl funktioniert?

Ori Horev
quelle
1
versuche eine Pipe für eine Pipe zu machen, ändere die Reihenfolge, mache tail -f file|grep -v "Y". Wenn die Ausgabe in Ordnung ist, fahren Sie mit dem Anhängen fort grep "X".
Aizuddin Zali

Antworten:

38

grepVerwenden Sie die --line-bufferedOption of grep, um die Zeilenpufferung zu aktivieren, da die Ausgabe von gepuffert wird :

tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'

Wenn Sie grepnicht über die Option verfügen, können Sie stdbufalternativ Folgendes verwenden:

tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
heemayl
quelle
1
Ich frage mich, wie stdbufsagt, libstdbuf.sowelche Einstellungen zu verwenden sind.
Kasperd
@kasperd: Umgebungsvariablen.
Nate Eldredge
1
@NateEldredge Ich habe bereits nach Umgebungsvariablen in der Ausgabe von gesucht diff -u <(env) <(stdbuf env)und keine gefunden. Aber jetzt merke ich, dass das, was ich hätte testen sollen, war diff -u <(env) <(stdbuf -oL env).
Kasperd
Ich bin auch die gleiche Art von Problem. In meinem Fall muss ich alle Zeilen drucken, die 'aaa' und 'bbb' enthalten. Die oben genannte erste Lösung funktioniert nicht. Die zweite Lösung funktioniert, da 'aaa' existiert und 'bbb' nicht existiert. beide existieren nicht. keine Ausgabe geben. mein befehl sieht so aus: tail -f test.txt | stdbuf -oL grep 'aaa' | grep 'bbb' es gibt keine ausgabe. Kannst du mir bitte Helfen.
So,
18

Ich finde normalerweise nützlicher awkfür diese Art von logischen Prüfungen:

tail -f /path/to/log | awk '/X/ && !/Y/'
#                           ^^^    ^^^^
#                   this I want    but not this

Getestet mit zwei Registerkarten, von denen eine ich schreibe seq 20 >> myfileund die andere zum Beispiel tail -f myfile | awk '/3/ && !/13/'.

fedorqui
quelle
15

Ein anderer Ansatz wäre, einen einzelnen grepAufruf anstelle von zwei zu verwenden und so das Pufferungsproblem zu vermeiden. Verwenden Sie einfach einen regulären Ausdruck, der mit Zeilen übereinstimmt, die aus 0 oder mehr Nicht-Y-Zeichen bestehen, dann ein X und dann 0 oder mehr Nicht-Ys bis zum Ende der Zeile. "

tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'
terdon
quelle