praktisches grep

Zeilen vor und nach dem Treffer ausgeben mit -B (–before-context) und -A (–after-context). Muss nicht weiter erklärt werden:

 grep -A1 -B2 "foo" /path/to/file

Zeichen vor und nach dem Treffer ausgeben geht mit -o (–only-matching) und -E (–extended-regexp). Der Parameter -E sorgt dafür, dass wonach gesucht wird als regulärer Ausdruck ausgewertet wird. Die Option -o zeigt nur das an was zutrifft, also nicht wie sonst üblich die komplette Zeile:

 grep -o -E ".{0,1}foo.{0,2}" /path/to/file

Dateinamen nicht angeben bei Treffern geht mit -h (–no-filename). Das ist gerade in der Kombination mit -E und -o praktisch wenn man das Ergebnis weiter verarbeiten möchte und nicht die Dateinamen mit einem dritten Programm (cut, awk…) wegparsen möchte:

 grep -Eho '' /path/to/files*

Steht alles auch so in der manpage 8-)

Update 2015-12-04:

grep -h -oP "ServerName \K.*" /etc/apache2/sites-enabled/*

(via)

Bash: Summe von Integers berechnen

Ich stand gerade wieder einmal vor dem Problem, dass ich aus einer Logdatei Meldungen nach dem Muster:

        582 media files copied.

extrahieren und davon dann nur die Zahlen zusammenzaehlen wollte. Ein gutes Beispiel um mal ein paar Tools fuer das Arbeiten mit Texten in der Shell vorzustellen.

Als erstes moechte ich alle Zeilen extrahieren. Dafuer nutze ich das Kommando grep:

grep "media files copied." /tmp/logfile

Ich erhalte daraufhin eine Liste mit allen Zeilen, die diesen String enthalten. Als naechstes moechte ich daraus die Nummern extrahieren. Der String beginnt immer mit acht Leerzeichen, und danach steht die Nummer. Hierfuer nutze ich das Kommendo cut, das mir einen String an bestimmten Trennzeichen aufteilt und mir davon die angegebene Spalte ausgibt. Als Trennzeichen eignet sich hier das Leerzeichen, da vor und nach der Nummer eines steht. Da acht Leerzeichen am Anfang sind, brauche ich die neunte Spalte. Dieses erreiche ich mit dem folgenden Code:

grep "media files copied." /tmp/logfile | cut -d " " -f 9

Ich leite also mit der Pipe | die Ausgabe des grep Kommandos weiter zu cut. Das Ergebnis ist eine Liste mit vielen Zahlen, die jede fuer sich in einer eigenen Zeile stehen. Um diese nun mit Hilfe des Kommandos bc zu addieren, muss daraus noch eine Rechenaufgabe werden. Ich greife dafuer auf das Programm paste zurueck. Hiermit kann ich Zeilen zusammenfuehren und dabei den Zeilenumbruch gegen ein von mir vorgegebenes Zeichen ersetzen. In diesem Fall moechte ich, dass jede Zeile nacheineander (seriell, nicht parallel) abgearbeitet wird, und der Zeilenumbruch gegen ein „+“ Zeichen ersetzt wird. Dementsprechend sieht mein Aufruf nun wie folgt aus:

grep "media files copied." /tmp/logfile | cut -d " " -f 9 | paste -sd+

Heraus kommt bei mir gerade das:

32+32+52+32+187+208+22+793+63+632+8+16+40+293+313+48+243+96+32+579+647+768+808+18+48+102+120+258+52+18+52+52+10+52+108+137+512+48+40+48+51+96+582+52+687+101+696+48+48+784+766+776+614+599+804+32+28+779+76+32+86+99+20+34+776+837+44+824+28+803+48

was ich nun nur noch zu bc pipen muss, und schon weiss ich, dass:

grep "media files copied." /tmp/logfile | cut -d " " -f 9 | paste -sd+  | bc

18869 Dateien kopiert wurden.

grep multiple lines

Ich weiss ja nicht, ob Sie schon wussten, aber grep kennt die Parameter -A fuer „after“ und -B fuer „before“. Beispiel:

# seq 10 | grep 5
5
# seq 10 | grep -A2 -B1 5
4
5
6
7

Sehr nett um z.B. in Logdateien zu gucken was vor und nach dem Suchmuster steht..