Ist es möglich, die Ausgabe des Schwanzes zu filtern?

11

Ich möchte eine Datei abschließen, aber nur Ausgabezeilen, die eine bestimmte Zeichenfolge enthalten. Ist das möglich?

Abe Miessler
quelle

Antworten:

32

benutze grep. Es ist nur für diesen Zweck gebaut.

Um Zeilen aus einem Ende von / var / log / syslog zu finden, die "cron" enthalten, führen Sie einfach Folgendes aus:

tail -f /var/log/syslog | grep cron

Und da es alles über stdin akzeptiert, können Sie es auch für die Ausgabe eines anderen Befehls verwenden, indem Sie auf die gleiche Weise wie oben (unter Verwendung des Symbols |) Pipings erstellen.

Ryan H.
quelle
8
Dies ist zwar im Wesentlichen richtig, es ist jedoch wichtig zu wissen, dass grepes puffert, wenn es nicht interaktiv verwendet wird, z. B. wenn es Teil einer längeren Pipeline ist. GNU grep 2.5.1 bietet die --line-bufferedOption, dies zu umgehen, wenn das Entfernen von grep aus der Pipeline keine Option ist. (Wenn ich grep sagen Puffer meine ich Sie nicht ausgegeben sehen , bis der Puffer so etwas wie 4k erreicht hat.)
kojiro
Um den vorherigen Kommentar zu ergänzen, arbeitet "tail -f" unter modernem Linux in einer Schleife und wartet auf weitere Eingaben in der Syslog-Datei. Lassen Sie den Schalter -f weg, damit der Befehl tatsächlich mit dem vorhandenen Inhalt der Datei endet: tail / var / log / syslog | grep cron
Gnudiff
7
tail -f /var/log/messages | grep "myfilterword"

Ich hoffe, das hilft.

Pablo
quelle
4

Hier sind einige andere Ideen, die zwar nicht so einfach sind, aber interessante zusätzliche Flexibilität bieten können:

Erstens können Sie mit awk anstelle von grep filtern:

tail -f /var/log/messages | awk '/myfilterword/'

das funktioniert genauso wie im Beispiel mit grep. Sie können dies erweitern, indem Sie die Leistung von awk verwenden, zum Beispiel:

tail -f /var/log/messages | \
awk '/myfilterword/ { for (i=6; i<=NF; i++) printf("%s ", $i); printf("\n")}'

Dadurch wird das 6. bis letzte Feld der Ausgabe gedruckt (Felder sind durch Leerzeichen getrennt).

Eine andere ähnliche Idee ist die Verwendung eines Perl-Einzeilers:

tail -f /var/log/messages | perl -ne "/myfilterword/ and print"

das funktioniert genau so grep. Vielleicht möchten Sie einen Zeilennummernzähler und nur das 6. Feld? Wie wäre es damit:

tail -f /var/log/messages | \ 
perl -lane "/myfilterword/ and printf \"%6d %s\n\",++\$a,\$F[6]"

Natürlich können all diese Dinge auch mit anderen Tools erledigt werden, aber ich wollte veranschaulichen, dass es hier einige unterhaltsame Möglichkeiten gibt, allgemeinere Sprachen wie awk oder perl zu verwenden.

Phil Hollenback
quelle
+1 großartige Ausarbeitung, wie man weiter expandiert als grep!
Pablo
2

Ein weiterer bemerkenswerter Trick, wenn Sie eine CSV-Datei mit Headern haben, die Sie weglassen möchten, z.

% cat data.txt
fruit        dessert        calories
Apple        Pie            770
Banana       Pudding        625
Cherry       Cobbler        990
% tail -n +2 data.txt
Apple        Pie            770
Banana       Pudding        625
Cherry       Cobbler        990

Es spielt keine Rolle, wie lange die Eingabe dauert tail, +n -2die erste Zeile wird weggelassen.

JeffG
quelle