Der Linux-Befehl `grep` dient dazu, Textmuster in Dateien zu suchen und passende Zeilen anzuzeigen. Er kann auch die Ausgaben anderer Befehle verarbeiten. Im Folgenden wird die Verwendung von `grep` detailliert erläutert.
Die Entstehungsgeschichte von grep
Der Befehl `grep` ist in der Linux- und Unix-Welt aus drei Hauptgründen bekannt. Erstens, seine enorme Nützlichkeit. Zweitens, die Vielzahl der verfügbaren Optionen kann überwältigend sein. Drittens, er wurde in kürzester Zeit entwickelt, um ein spezifisches Problem zu lösen. Die ersten beiden Gründe sind beeindruckend, der dritte ist eher eine Anekdote.
Ken Thompson hatte die Funktionalität der Suche nach regulären Ausdrücken aus dem Texteditor `ed` (ausgesprochen „ee-dee“) extrahiert und ein eigenes kleines Programm zur Durchsuchung von Textdateien erstellt. Sein Abteilungsleiter bei den Bell Labs, Doug Mcilroy, informierte Thompson über ein Problem, mit dem ein Kollege namens Lee McMahon konfrontiert war.
McMahon versuchte, die Autorenschaft der Federalist Papers durch Textanalyse zu bestimmen. Er benötigte ein Werkzeug, das nach bestimmten Phrasen und Zeichenketten in Textdateien suchen konnte. Thompson investierte etwa eine Stunde an diesem Abend, um sein Werkzeug in ein allgemein verwendbares Hilfsprogramm umzuwandeln und nannte es `grep`. Der Name stammt vom `ed`-Befehl `g/re/p`, was „globale Suche nach regulären Ausdrücken“ bedeutet.
Ein Video, in dem Thompson mit Brian Kernighan über die Entstehung von `grep` spricht, finden Sie hier.
Grundlegende Suchen mit grep
Um in einer Datei nach einer bestimmten Zeichenkette zu suchen, geben Sie den Suchbegriff und den Dateinamen in der Befehlszeile an:
grep Suchbegriff Dateiname
Passende Zeilen werden dann angezeigt. In diesem Fall wäre es eine einzelne Zeile, wobei der gefundene Text hervorgehoben ist. Dies ist meistens so voreingestellt, da `grep` in den meisten Linux-Distributionen mit folgendem Alias versehen ist:
alias grep='grep --colour=auto'
Betrachten wir ein Beispiel, bei dem mehrere Zeilen übereinstimmen. Wir suchen in einer Log-Datei nach dem Wort „Durchschnitt“. Da wir nicht sicher sind, ob das Wort groß- oder kleingeschrieben ist, verwenden wir die Option `-i` (Groß-/Kleinschreibung ignorieren):
grep -i Durchschnitt geek-1.log
Jede Zeile, die den Suchbegriff enthält, wird angezeigt, und der gefundene Text ist hervorgehoben.
Um die Zeilen anzuzeigen, die *nicht* übereinstimmen, verwenden wir die Option `-v` (Übereinstimmung invertieren):
grep -v Mem geek-1.log
Hier erfolgt keine Hervorhebung, da es sich um die Zeilen handelt, die nicht mit dem Suchmuster übereinstimmen.
Wir können `grep` auch dazu bringen, keine Ausgabe anzuzeigen. Das Ergebnis wird als Rückgabewert an die Shell übermittelt. Ein Rückgabewert von Null bedeutet, dass die Zeichenkette gefunden wurde, und Eins bedeutet, dass sie nicht gefunden wurde. Wir können den Rückgabecode mit dem `$?` speziellen Parameter überprüfen:
grep -q average geek-1.log
echo $?
grep -q wdzwdz geek-1.log
echo $?
Rekursive Suchen mit grep
Um in verschachtelten Verzeichnissen und Unterverzeichnissen zu suchen, verwenden Sie die Option `-r` (rekursiv). Beachten Sie, dass Sie hier keinen Dateinamen, sondern einen Pfad angeben. Wir suchen im aktuellen Verzeichnis „.“ und allen Unterverzeichnissen:
grep -r -i memfree .
Die Ausgabe zeigt das Verzeichnis und den Dateinamen jeder Zeile, die das Suchmuster enthält.
Wir können `grep` veranlassen, symbolischen Links zu folgen, indem wir die Option `-R` (rekursive Dereferenzierung) verwenden. In diesem Verzeichnis haben wir einen symbolischen Link namens „logs-folder“, der auf `/home/dave/logs` zeigt.
ls -l logs-folder
Wiederholen wir die vorherige Suche mit der Option `-R`:
grep -R -i memfree .
Der symbolische Link wird nun verfolgt, und das Verzeichnis, auf das er zeigt, wird ebenfalls von `grep` durchsucht.
Suche nach ganzen Wörtern
Standardmäßig stimmt `grep` mit einer Zeile überein, wenn der Suchbegriff irgendwo in dieser Zeile vorkommt, auch innerhalb eines anderen Wortes. Sehen wir uns das folgende Beispiel an. Wir suchen nach dem Wort „free“:
grep -i free geek-1.log
Das Ergebnis sind Zeilen, die die Zeichenkette „free“ enthalten, aber nicht als separates Wort. Sie sind Teil der Zeichenkette „MemFree“.
Um zu erzwingen, dass `grep` nur mit separaten „Wörtern“ übereinstimmt, verwenden wir die Option `-w` (Wort-Regulärer Ausdruck):
grep -w -i free geek-1.log
echo $?
Dieses Mal gibt es keine Ergebnisse, da das Wort „free“ nicht als eigenständiges Wort in der Datei vorkommt.
Verwendung mehrerer Suchbegriffe
Die Option `-E` (erweiterter regulärer Ausdruck) ermöglicht die Suche nach mehreren Wörtern. (Die Option `-E` ersetzt die veraltete `egrep`-Version von `grep`.)
Dieser Befehl sucht nach den Suchbegriffen „average“ und „memfree“:
grep -E -w -i "average|memfree" geek-1.log
Es werden alle Zeilen angezeigt, die mit einem der Suchbegriffe übereinstimmen.
Sie können auch nach mehreren Begriffen suchen, die nicht unbedingt ganze Wörter sein müssen, aber auch ganze Wörter sein können.
Mit der Option `-e` (Muster) können Sie mehrere Suchbegriffe in der Befehlszeile verwenden. Wir verwenden hier Klammern für reguläre Ausdrücke, um ein Suchmuster zu erstellen. Es weist `grep` an, mit jedem Zeichen innerhalb der Klammern übereinzustimmen. In diesem Fall bedeutet es, dass `grep` sowohl mit „kB“ als auch mit „KB“ übereinstimmt.
Beide Zeichenketten werden abgeglichen, und tatsächlich enthalten einige Zeilen beide.
Exakte Zeilenübereinstimmung
Die Option `-x` (Zeilen-Regulärer Ausdruck) findet nur Zeilen, bei denen die *gesamte* Zeile mit dem Suchbegriff übereinstimmt. Suchen wir nach einem Zeitstempel, von dem wir wissen, dass er nur einmal in der Protokolldatei vorkommt:
grep -x "20-Jan--06 15:24:35" geek-1.log
Die passende Zeile wird gefunden und angezeigt.
Das Gegenteil davon ist, dass wir nur die Zeilen anzeigen, die *nicht* übereinstimmen. Dies kann nützlich sein, wenn Sie sich Konfigurationsdateien ansehen. Kommentare sind hilfreich, aber manchmal ist es schwierig, die tatsächlichen Einstellungen zwischen all den Kommentaren zu erkennen. Hier ist die Datei `/etc/sudoers`:
Wir können die Kommentarzeilen auf folgende Weise herausfiltern:
sudo grep -v "#" /etc/sudoers
Das ist jetzt viel einfacher zu überblicken.
Nur passenden Text anzeigen
Es kann vorkommen, dass Sie nicht die gesamte übereinstimmende Zeile, sondern nur den übereinstimmenden Text sehen möchten. Die Option `-o` (nur übereinstimmend) bewirkt genau das.
grep -o MemFree geek-1.log
Die Ausgabe wird so reduziert, dass nur der Text angezeigt wird, der dem Suchbegriff entspricht, und nicht die gesamte Zeile.
Zählen mit grep
`grep` kann nicht nur Text durchsuchen, sondern auch numerische Informationen bereitstellen. Wir können `grep` auf verschiedene Arten zählen lassen. Wenn wir wissen möchten, wie oft ein Suchbegriff in einer Datei vorkommt, verwenden wir die Option `-c` (Zählen):
grep -c average geek-1.log
`grep` meldet, dass der Suchbegriff 240 Mal in der Datei vorkommt.
Wir können `grep` auch dazu bringen, die Zeilennummer für jede passende Zeile anzuzeigen. Verwenden Sie dafür die Option `-n` (Zeilennummer):
grep -n Jan geek-1.log
Die Zeilennummer jeder passenden Zeile wird am Anfang angezeigt.
Um die Anzahl der angezeigten Ergebnisse zu reduzieren, verwenden Sie die Option `-m` (maximale Anzahl). Wir beschränken die Ausgabe auf fünf passende Zeilen:
grep -m5 -n Jan geek-1.log
Kontext hinzufügen
Oft ist es hilfreich, zusätzliche Zeilen (möglicherweise nicht passende Zeilen) für jede passende Zeile anzuzeigen. Dies kann helfen, zu erkennen, welche der passenden Zeilen für Sie wirklich relevant sind.
Um einige Zeilen *nach* der passenden Zeile anzuzeigen, verwenden wir die Option `-A` (nach dem Kontext). In diesem Beispiel bitten wir um drei Zeilen:
grep -A 3 -x "20-Jan-06 15:24:35" geek-1.log
Um einige Zeilen *vor* der passenden Zeile anzuzeigen, verwenden Sie die Option `-B` (Kontext vor):
grep -B 3 -x "20-Jan-06 15:24:35" geek-1.log
Und um Zeilen sowohl vor als auch nach der passenden Zeile einzuschließen, verwenden Sie die Option `-C` (Kontext):
grep -C 3 -x "20-Jan-06 15:24:35" geek-1.log
Passende Dateien anzeigen
Um die Namen der Dateien anzuzeigen, die den Suchbegriff enthalten, verwenden wir die Option `-l` (Dateien mit Übereinstimmung). Um herauszufinden, welche C-Quellcodedateien Verweise auf die Headerdatei `sl.h` enthalten, verwenden wir folgenden Befehl:
grep -l "sl.h" *.c
Es werden nur die Dateinamen aufgelistet, nicht die passenden Zeilen.
Und natürlich können wir auch nach Dateien suchen, die den Suchbegriff *nicht* enthalten. Die Option `-L` (Dateien ohne Übereinstimmung) macht genau das.
grep -L "sl.h" *.c
Zeilenanfang und -ende
Wir können `grep` zwingen, nur Übereinstimmungen anzuzeigen, die entweder am Anfang oder am Ende einer Zeile vorkommen. Der reguläre Ausdrucksoperator „^“ entspricht dem Anfang einer Zeile. Praktisch alle Zeilen in der Protokolldatei enthalten Leerzeichen, aber wir suchen nach Zeilen, die ein Leerzeichen als *erstes* Zeichen haben:
grep "^ " geek-1.log
Die Zeilen, die ein Leerzeichen als erstes Zeichen haben – also am Zeilenanfang – werden angezeigt.
Um das Zeilenende abzugleichen, verwenden wir den regulären Ausdrucksoperator „$“. Wir suchen nach Zeilen, die mit „00“ enden:
grep "00$" geek-1.log
Die Ausgabe zeigt die Zeilen an, deren letzte Zeichen „00“ sind.
Pipes mit grep verwenden
Selbstverständlich können Sie die Eingabe an `grep` weiterleiten, die Ausgabe von `grep` an ein anderes Programm weiterleiten und `grep` in eine Kette von Pipes einbetten.
Nehmen wir an, wir möchten alle Vorkommen der Zeichenkette „ExtractParameters“ in unseren C-Quellcodedateien anzeigen. Wir wissen, dass es viele sein werden, daher leiten wir die Ausgabe zu `less` um:
grep "ExtractParameters" *.c | less
Die Ausgabe wird dann in `less` angezeigt.
Auf diese Weise können Sie die Dateiliste durchgehen und die Suchfunktion von `less` verwenden.
Wenn wir die Ausgabe von `grep` zu `wc` umleiten und die Option `-l` (Zeilen) verwenden, können wir die Anzahl der Zeilen zählen in den Quellcodedateien, die „ExtractParameters“ enthalten. (Wir könnten dies mit der Option `grep -c` (Zählen) erreichen, aber dies ist eine gute Möglichkeit, die Umleitung der Ausgabe von `grep` zu veranschaulichen.)
grep "ExtractParameters" *.c | wc -l
Mit dem nächsten Befehl leiten wir die Ausgabe von `ls` an `grep` und die Ausgabe von `grep` an `sort` weiter. Wir listen die Dateien im aktuellen Verzeichnis auf und wählen diejenigen aus, die die Zeichenkette „Aug“ enthalten. Anschließend sortieren wir die Ergebnisse nach Dateigröße:
ls -l | grep "Aug" | sort +4n
Lassen Sie uns dies aufschlüsseln:
`ls -l`: Führt eine detaillierte Auflistung der Dateien mit `ls` aus.
`grep „Aug“`: Wählt die Zeilen aus der `ls`-Liste aus, die „Aug“ enthalten. Beachten Sie, dass dies auch Dateien mit dem Namen „Aug“ finden würde.
`sort +4n`: Sortiert die Ausgabe von `grep