26.2 Vom Suchen und Finden: ein kurzer Überblick
Zu den Hauptaufgaben der Systemadministration gehören das Durchforsten von LogDateien genauso wie das regelmäßige Extrahieren von Informationen und das Erstellen von Reports aus diesen Informationen. Daher nimmt das Suchen und Verarbeiten von Textdateien einen wichtigen Stellenwert innerhalb der täglichen Arbeit ein.
26.2.1 Die Detektive: »grep«, »sed« und »awk«
Zu den wichtigsten Tools gehören grep, sed und awk, die manchmal nach den Anfangsbuchstaben unter dem Kürzel GAS zusammengefasst werden.
Die Hauptaufgabe von grep besteht in dem Durchsuchen von Textdateien und in der Ausgabe der Zeilen, die einen Treffer enthalten. Für die Herkunft des Begriffs grep gibt es zwei Erklärungsansätze: Zum einen soll es für global/regular expression/print stehen und zum anderen für global search for a regular expression and print out matched lines.
Bei sed (den Stream Editor) liegt der Fokus auf der zeilenweisen Veränderung von Textzeilen.
awk, dessen Name sich aus den Anfangsbuchstaben der Nachnamen seiner drei Autoren zusammensetzt – Alfred V. Aho, Peter J. Weinberger und Brian W. Kernighan –, ist das mächtigste der drei Tools. awk bringt eine eigene Programmiersprache mit. Allerdings wird es häufig nur dazu verwendet, Teile einer Zeile formatiert auszugeben, eine Aufgabe, die auch cut erfüllen könnte. awk beherrscht alles, was sed und grep können, ist allerdings etwas schwieriger zu lernen.
Obwohl Perl an Bedeutung verloren hat, ist es ungeschlagen bei Suchvorgängen, die sich im »Kommandozeilenmodus« einfach und schnell erledigen lassen. Nehmen wir das folgende Beispiel:
dirk@example:/# ps -ef | grep ssh | grep -v grep
Listing 26.1 Laufende »ssh«-Prozesse finden: »grep«
Dieser Befehl listet alle Prozesse auf, bei denen das Wort ssh in der Ausgabe von ps -ef zu finden ist. Das grep -v grep am Ende sorgt dafür, dass der Suchprozess sich nicht selbst findet. Wir haben also einen ps-Aufruf und zwei grep-Aufrufe. Mit awk reduziert sich der Aufwand auf einen ps-Aufruf und einen awk-Aufruf, wie dieser Befehl zeigt:
dirk@example:/# ps -ef | awk '/ssh/ && ! /awk/ {print}'
Listing 26.2 Laufende »ssh«-Prozesse finden: »awk«
Die Befehle in den Listing 26.1 und sind nicht nur ein Beispiel dafür, dass viele Wege nach Rom führen, sondern vor allem auch dafür, dass Sie Ihre Tools gut kennen sollten. Meist ist für die Lösung einer Problemstellung nur ein Tool nötig, und Zusatztools sind überflüssig (ein Paradebeispiel dafür ist cat datei.txt | grep XYZ).
Wie jeder gute Handwerker müssen Sie dafür Ihr Werkzeug gut beherrschen. Ein Blick in die Manpages eines Tools eröffnet einem Sysadmin meist ungeahnte Möglichkeiten. Scheuen Sie sich also nicht, auch einmal nachzulesen, wie mächtig die von Ihnen eingesetzten Programme sind.
26.2.2 Reguläre Ausdrücke verstehen und anwenden
Für viele sind reguläre Ausdrücke ein Buch mit sieben Siegeln. Dabei sind sie eines der besten Werkzeuge, um effiziente Skripte zu erstellen. Bei regulären Ausdrücken, die oft auch als Regex[ 41 ] bezeichnet werden, handelt es sich um syntaktische Regeln zur Beschreibung von Mengen oder Untermengen einer Zeichenkette. Mit diesen Regeln können Zeichenketten extrahiert werden (Mustersuche oder Pattern Matching[ 42 ]), auch wenn deren genaue Abfolge nicht bekannt ist. Ein weiterer Anwendungszweck ist das Suchen und Ersetzen, das mit regulären Ausdrücken ebenfalls vereinfacht werden kann.
Viele Programme verwenden eigene Implementierungen von regulären Ausdrücken, die sich in Umfang und Syntax unterscheiden. Die folgenden drei großen decken fast alle zu findenden Implementierungen ab:
-
Basic Regular Expressions (BRE)
Dies sind nach dem POSIX-Standard definierte reguläre Ausdrücke – sie finden zum Beispiel beim Editor vim Anwendung. -
Extended Regular Expressions (ERE)
Ebenfalls nach dem POSIX-Standard definierte reguläre Ausdrücke mit erweitertem Funktionsumfang – sie finden zum Beispiel bei egrep Anwendung. -
Perl Compatible Regular Expressions (PCRE)
Reguläre Ausdrücke nach dem PCRE-Standard orientieren sich an der Implementierung von Regex in der Programmiersprache Perl.
Die Implementierungen unterscheiden sich vor allem in der Syntax. Bei BREs muss die Sonderfunktion von Spezialzeichen durch einen umgekehrten Schrägstrich – Backslash (\) – auch innerhalb der Syntax aufgehoben werden, zum Beispiel: s\{2\}. Dies ist hingegen bei EREs nicht notwendig, zum Beispiel: s{2}. Bei regulären Ausdrücken nach dem PCRE-Standard wird der erste Rückbezug durch $1 angegeben, ansonsten werden diese mit einem führenden Backslash (\) dargestellt.
BRE | ERE | PCRE | Bedeutung |
---|---|---|---|
ab | ab | ab | die Zeichenkette »ab« in genau dieser Reihenfolge |
. | . | . | ein beliebiges Zeichen (bei Dateinamenexpansion das »?«) |
z* | z* | z* | beliebig oft »z«, auch kein Vorkommen |
x\+ | x+ | x+ | mindestens einmal »x« |
a\{6\} | a{6} | a{6} | genau sechsmal »a« |
a\{3,\} | a{3,} | a{3,} | mindestens dreimal »a« |
a\{2,4\} | a{2,4} | a{2,4} | zwei- bis viermal »a« |
[abc] | [abc] | [abc] | ein einzelnes »a«, »b« oder »c« |
[a-z] | [a-z] | [a-z] | ein beliebiges Zeichen zwischen »a« und »z« |
[^ab] | [^ab] | [^ab] | ein beliebiges Zeichen, ohne »a« und ohne »b« |
y\? | y? | y? | einmal oder keinmal »y« |
\(...\) | (...) | (...) | Mit Klammern werden Ausdrücke für Rückbezüge gruppiert. |
a\|b | a|b | a|b | entweder »a« oder »b« |
^ | ^ | ^ | Zeilenanfang |
$ | $ | $ | Zeilenende |
ab | ab | ab | die Zeichenkette »ab« in genau dieser Reihenfolge |
\< | \< | \< | Anfang eines Worts |
\> | \> | \> | Wortende |
\w | \w | \w | alphanumerische Zeichen und der Unterstrich (Wortzeichen) |
\W | \W | \W | kein Wortzeichen |
\d | \d | \d | eine Ziffer |
\D | \D | \D | keine Ziffer |
\s | \s | \s | Leerzeichen (Whitespace) |
\S | \S | \S | kein Leerzeichen |
Tabelle 26.1 Syntax der regulären Ausdrücke
Tabelle 26.1 zeigt die Unterschiede in der Syntax bei den einzelnen Implementierungen von regulären Ausdrücken. Wenn mit regulären Ausdrücken nach Sonderzeichen gesucht werden soll, muss deren Sonderfunktion mit einem Backslash (\) aufgehoben werden. Dies darf aber nicht mit der Dateinamensexpansion (Globbing) verwechselt werden, da hier eine andere Syntax angewandt wird. Ein zentrales Element von regulären Ausdrücken sind Rückbezüge. Mit diesen können nicht nur Zeichenketten extrahiert, ein Suchen und Ersetzen durchgeführt, sondern auch Vergleiche vorgenommen werden. Für das Durchsuchen eines Wörterbuchs sei folgende Aufgabenstellung vorausgesetzt:
Suchen Sie nach allen Begriffen, die aus fünf Buchstaben bestehen und von vorn und hinten gelesen gleich aussehen, wie beispielsweise »rotor«.
Dies kann sowohl über egrep, als auch mit Perl erreicht werden:
### egrep
d@example:/# egrep "^(.)(.)(.)\2\1$" /usr/share/dict/american-english
### Perl
d@example:/# perl -ne 'print if /^(.)(.)(.)\2\1$/' /usr/share/dict/american-english
Listing 26.3 Suche und Rückgabe mit »egrep«
Beide Befehle liefern dasselbe Ergebnis zurück. In den aktuellen Versionen von grep können auch unterschiedliche reguläre Ausdrucksarten angewandt werden. Mit egrep (oder auch grep -E) wird ein ERE verwendet. Mit dem Aufruf von grep -P wird ein PCRE benutzt. Je nach Art des regulären Ausdrucks ist grep mit EREs um den Faktor 2 bis 10 langsamer als mit PCREs. Auch Linux-Shells, etwa die bash ab Version 3, verstehen reguläre Ausdrücke, sodass Sie diese direkt in Skripten verwenden können. Listing 26.4 zeigt ein kleines Beispiel für einen bash-Regex:
#!/bin/bash
FILENAME=dh-20091005-ausgabe-006.ogg
REGEX='^dh-([0-9]{4})([0-9]{2})([0-9]{2})-ausgabe-([0-9]{3}).ogg$'
if [[ $FILENAME =~ $REGEX ]]
then
jahr=${BASH_REMATCH[1]}
monat=${BASH_REMATCH[2]}
tag=${BASH_REMATCH[3]}
episode=${BASH_REMATCH[4]}
fi
echo "Jahr: $jahr, Monat: $monat, Tag: $tag, Episode: $episode"
Listing 26.4 Beispiel-»Regex« in einem »bash«-Skript
Hier wird über den regulären Ausdruck REGEX angegeben, aus welchen Teilen FILENAME besteht. Die if-Abfrage wendet den regulären Ausdruck aufgrund des Vergleichsoperators =~ an. Die Variablen werden über das bash-interne Array BASH_REMATCH den einzelnen Rückbezügen zugewiesen.