<< Vorheriger Befehl Nächster Befehl >>

Bash-Befehle und Bash-Programmierung

© Klaus Gerhardt, 08.2005

(Copyright, Nutzungsbedingungen, Haftungsausschluss, s.u.)


grep und Reguläre Ausdrücke (regular expressions)

grep gibt Zeilen aus, die einem Suchmuster entsprechen
Reguläre Ausdrücke (regular expressions)
Die Praxis, Reguläre Ausdrücke in der Anwendung mit grep
grep mit find kombinieren
zgrep sucht in komprimierten Dateien

grep gibt Zeilen aus, die einem Suchmuster entsprechen

Syntax:

grep [Optionen] Muster Datei1 [Datei2] ... [DateiN]
grep [Optionen] -e Muster1 -e Muster2 ... [-e MusterN] Datei1 [Datei2] ... [DateiN]


grep sucht in den angegebenen Dateien nach Zeilen in welchen das vorgegebene Muster vorkommt und gibt die Treffer am Bildschirm aus. Die Option -e wirkt wie ein Oder (OR). Man kann damit also nach mehreren Mustern gleichzeitig suchen. Diese Muster sind sogenannte Reguläre Ausdrücke (Regular Expressions). Die Muster müssen in manchen Fällen in Anführungszeichen stehen, damit die Suche erfolgreich ist.

Es gibt unterschiedliche Varianten von grep wie GNU grep, egrep, GNU egrep, fgrep, etc. Zudem gibt es noch weitere Programme die mit Regulären Ausdrücken arbeiten wie sed und perl. Diese Beschreibung hier gilt für GNU grep. Abweichungen bei anderen Programmen bzw. Befehlen sind den jeweiligen Manual-Seiten zu entnehmen.

Optionen:

-c
(count) gibt nur die Anzahl der Zeilen an in denen das Suchmuster gefunden wurde, jedoch nicht die Zeilen selbst. Wenn die Option -v verwendet wird, werden die Zeilen gezählt die das Muster nicht enthalten
-e
Muss verwendet werden wenn das Muster mit "-" beginnt. Kann aber auch verwendet werden um mehrere Muster mit "Oder" zu verknüpfen.
-H
gibt den Dateinamen für jeden Treffer mit aus
-i
(ignore case) ignoriert die Gross-/Kleinschreibung des Musters
-m Anzahl
begrenzt die Anzahl der ausgegebenen Treffer auf Anzahl Zeilen
-n
die Zeilennummern der gefundenen Zeilen, aus den durchsuchten Dateien werden der Ausgabe vorangestellt
-r, -R
durchsucht rekursiv alle Dateien in allen Unterverzeichnissen. Dies funktioniert aber nur mit der Wildcard "*" einwandfrei. Aus diesem Grunde verwendet man für die rekursive Suche grep zusammen mit dem Befehl find (s. Beispiel unten).
-s
(supress error messages) unterdrückt Fehlermeldungen
-v
invertiert die Ausgabe, d.h. es werden die Zeilen in denen das Suchmuster nicht vorkommt am Bildschirm ausgegeben
Zum Seitenanfang

Reguläre Ausdrücke

Mit Regulären Ausdrücken wird eine festgelegte Zeichenfolge beschrieben. Hierzu werden Meta-Zeichen, (metacharacters) auch Platzhalter genannt und Operatoren verwendet.

Achtung! Auch wenn Reguläre Ausdrücke eine gewisse Ähnlichkeit mit Wildcards aufweisen sind sie doch recht unterschiedlich und dienen unterschiedlichen Zwecken. Mit Reguläre Ausdrücken sucht man nach Zeichenfolgen innerhalb von Dateien. Wildcards dienen der Suche nach Dateien.

Prinzipiell steht jedes Zeichen erst einmal für sich selbst. Wenn ich als Muster

"Suchtext"

eingebe. Wird also nach dem Vorkommen der Zeichenfolge "Suchtext" in den angegebenen Dateien gesucht.

Behandlung von Sonderzeichen: Sonderzeichen wie ?, +, {, }, |, (, ), ., ", \ müssen mit einem Backslash "\" maskiert werden.


Platzhalter

Mit der Hilfe von Platzhaltern kann man die Suche spezifizieren. Das Suchmuster muss damit nicht mehr exact der gesuchten Zeichenkette entsprechen,sondern kann damit abstrakt beschrieben werden.

.         steht für ein beliebiges Zeichen
[ ] der Ausdruck in der Klammer ist Platzhalter für genau ein Zeichen aus der Liste in der Klammer
[^ ] hiermit werden alle Zeichen aus der Liste ausgeschlossen. Es handelt sich wiederum um den Platzhalter für genau ein Zeichen
Sonderregelungen:
]         wenn man nach diesem Zeichen sucht muss es innerhalb der Klammern am Anfang stehen
^ dieses darf irgendwo, jedoch nicht am Anfang stehen
- dieses muss am Ende stehen

Beispiele:

" s" " " gefolgt von "s"
e.t sucht nach "e" + beliebiges Zeichen + "t"
[abc] eines der Zeichen "a", "b", "c"
[^abc] keines der Zeichen "a", "b", "c"
[^t] kein "t" an dieser Stelle
ich[^t] findet "ich", aber nicht "nicht"
[a-f] die Buchstaben "a", "b", "c", "d", "e" und "f"
[a-z] alle Kleinbuchstaben
[A-Z] alle Grossbuchstaben
[a-zäöüßA-ZÄÖÜ] alle Klein- und Grossbuchstaben incl. deutscher Sonderzeichen
[a-zA-Z-] alle Klein- und Grossbuchstaben und "-"
[0-9] alle Zahlen
[a-zA-Z0-9] alle alphanumerische Zeichen (o. deutsche Sonderzeichen)


Benannte Klassen (Named Classes)

Die bennanten Klassen sind vordefinierte Zeichenkombinationen für die Platzhalter in eckigen Klammern.

[:lower:]       entspricht       a-z
[:upper:] entspricht A-Z
[:alpha:] entspricht a-zA-Z und [:lower:] + [:upper:]
[:digit:] entspricht 0-9
[:alnum:] entspricht 0-9a-zA-Z und [:alpha:] + [:digit:]
[:space:] entspricht einem Leerschritt

Die benannten Klassen müssen für die Verwendung nochmals in eckige Klammer geschrieben werden. Im Muster entspricht

[[:alnum:]]    diesem Ausdruck    [0-9a-zA-Z]


Begrenzungen suchen

Mit Hilfe dieser Metazeichen kann man die Begrenzungen von Zeilen und Wörtern beschreiben.

^ steht für den Zeilenanfang
$ steht für das Zeilenende
\< steht für Wortanfang
\> steht für Wortende
\b steht Wortanfang oder Wortende

Beispiele:

^D sucht nach grossem D am Zeilenanfang
^.a sucht nach einem beliebigen Zeichen + "a" am Zeilenanfang
\.$ sucht nach einem "." am Ende der Zeile
n\.$ sucht nach "n" und "." am Ende der Zeile
\<ich\> sucht nach dem ganzen Wort "ich"


Wiederholungs-Operatoren



* das vorangegangene Zeichen darf beliebig oft oder auch gar nicht auftreten
? das vorangegangene Zeichen darf gar nicht oder einmal auftreten
+ das vorangegangene Zeichen darf beliebig oft, muss aber mindestens einmal auftreten
{n} das vorangegangene Zeichen tritt n-mal auf
{n,} das vorangegangene Zeichen tritt n-mal oder öfter auf
{n,m} das vorangegangene Zeichen tritt mindestens n-mal und maximal m-mal auf

Beispiele:

dass? findest "das" und "dass"
[dD]as{1,2} findet "das", "Das", "dass" und "Dass"
[dD]as\{1,2\} Aber Achtung! Diese beiden Zeichen "{", "}" müssen mit einem "\" maskiert werden.
[[:space:]]\{2\} findet 2 Leerzeichen.


Sonstiges



| verbindet zwei oder mehr Ausdrücke mit einem "Oder" (OR)
() stellt Gruppierungen her. Wiederholungs-Operatoren können auch auf Gruppierungen angewendet werden.

Beispiele:

(da|na)ss findet "dass" und "nass"
\(da\|na\)ss Aber Achtung! Diese Zeichen "(", "|", ")" müssen mit einem "\" maskiert werden.
Karl\(-Heinz\)\? findet Karl und Karl-Heinz


Zum Seitenanfang

Die Praxis, Reguläre Ausdrücke in der Anwendung mit grep


Die Beispiele oben dienten dem Verständnis der Regulären Ausdrücke. In der Praxis, beim Arbeiten mit grep, muss man die Suchmuster ggf. noch in Anführungszeichen einschliessen und die Maskierung der Sonderzeichen berücksichtigen.

Zudem ist die Erstellung von Regulären Ausdrücken doch meist komplexer als aus den Beispielen oben ersichtlich ist. Aus diesem Grunde gibt es weiter unten einige Schritt-für-Schritt-Beispiele in denen ich demonstriere wie man die Suche verfeinern kann um das gewünschte Ergebnis zu ereichen.

Einfache Beispiele:

sucht nach dem Regulären Ausdruck "ich" in der Datei qqk

grep "ich" qqk

oder

grep "ich" < qqk

... und leitet die Ausgabe nach qqk1

grep "ich" < qqk > qqk1

durchsucht alle *.tex-Dateien im aktuellen Verzeichnis nach der Zeichenfolge "emacs"

grep "emacs" *.tex

ermittelt mit der Option -c wie oft die arctan -Funktion in den *.c Dateien verwendet wird

grep -c arctan\(.*\) *.c

Hier wird es etwas komplexer

Dies ist die Datei "adressen", die für einige der nächsten Suchen verwendet wird:

Meier Müller Meyer Schmidt Hohn Maier Mayer Mayr Paule

sucht nach Meier, Meyer, Meyer und Mayer in der Datei adressen

klaus@athlon:~/bin/test> grep M[ae][iy]er adressen Meier Meyer Maier Mayer

und die beiden nächsten Beispiele auch noch nach allen "Meiers" ohne "e" am Ende.

klaus@athlon:~/bin/test> grep "M[ae][iy]e\?r" adressen Meier Meyer Maier Mayer Mayr

klaus@athlon:~/bin/test> grep "M[ae][iy]e\{0,1\}r" adressen Meier Meyer Maier Mayer Mayr

Dies ist die Datei "gruppe", die für die Beispiele unten verwendet wird:

dass mass nass trocken maß maßlos dieses hallo hallohallo, ist da wer? wort1 wort2 grep -V

Option -e muss verwendet werden, da der Suchbegriff am Anfang ein Minus "-" enthält:

klaus@athlon:~/bin> grep -e "-V" gruppe grep -V

Ein Beispiel von oben auf der Kommandozeile ausgeführt:

klaus@athlon:~/bin> grep "\(da\|na\)ss" gruppe dass nass

Sucht nach wort1 oder wort2:

klaus@athlon:~/bin> grep "wort1\|wort2" gruppe wort1 wort2

Das lässt sich auch so lösen:

klaus@athlon:~/bin> grep -e "wort1" -e "wort2" gruppe wort1 wort2

Oder so:

klaus@athlon:~/bin> grep "wort\(1\|2\)" gruppe wort1 wort2

Eine Gruppierung kann auch mit einem Wiederholungs-Operator vervielfacht werden:

klaus@athlon:~/bin> grep "\(hallo\)\{2\}" gruppe hallohallo, ist da wer?

Und als nächstes jetzt ein etwas komplexeres Beispiel für Gruppierungen (in 2 Schritten):

Gesucht werden Benutzer mit der Gruppen-ID 100. Die Gruppen-ID steht in der Datei passwd im 4. Feld. Jedes der 3 davorstehenden Felder kann man mit diesem Ausdruck beschreiben "[^:]*:"

Hier jetzt erst einmal die Suche "voll ausgeschrieben":

athlon:/etc # grep [^:]*:[^:]*:[^:]*:100 passwd games:x:12:100:Games account:/var/games:/bin/bash klaus:x:1000:100:Klaus Gerhardt:/home/klaus:/bin/bash test:x:1001:100:test:/home/test:/bin/bash

Und jetzt die ersten 3 Felder in einer Gruppierung zusammengefasst. Achtung! Der Reguläre Ausdruck muss jetzt in Anführungszeichen stehen, sonst findet keine Suche statt:

athlon:/etc # grep "\([^:]*:\)\{3\}100" passwd games:x:12:100:Games account:/var/games:/bin/bash klaus:x:1000:100:Klaus Gerhardt:/home/klaus:/bin/bash test:x:1001:100:test:/home/test:/bin/bash

Als nächstes die Suche nach dem doppel "d" in mehreren Schritten:

Dies ist die Datei doppeld:

einfach d Doppel dd Dreifach ddd und noch ein Doppel dd_ende

Mein erster Versuch. Es sollen alle Textstellen gefeunden werden in denen ein doppeltes "d" vorkommt. 3-fach "d" sollen aber ausgeschlossen sein. Mein Ausdruck sagt: finde alle Zeilen in denen "dd" vorkommt.

klaus@athlon:~/bin> grep "d\{2\}" doppeld Doppel dd Dreifach ddd und noch ein Doppel dd_ende

Das 3-fach d "d" wird bei meiner Suche jedoch auch gefunden. Denn "dd" ist in "ddd" ja auch enthalten. Ich versuche es deshalb anders. Der nächste Ausdruck sagt: Vom Anfang der Zeile an kein d, dies gar nicht oder beliebig oft, dann dd und zum Ende der Zeile hin kein d, dies gar nicht oder beliebig oft.

klaus@athlon:~/bin> grep "^[^d]*d\{2\}[^d]*$" doppeld Doppel dd

Jetzt wird allerdings die letzte Zeile aus der Datei doppeld nicht gefunden. Da diese Zeile ein einzelnes d in dem "und" enthält, wird sie von meinem Ausdruck "Vom Anfang der Zeile an kein d, dies gar nicht oder beliebig oft" ausgeschlossen.

Ich starte noch einen Versuch. Der unten stehende Ausdruck heisst: Zeilenanfang oder kein d, dann dd und dann kein d oder Zeilenende.

klaus@athlon:~/bin> grep "\(^\|[^d]\)d\{2\}\([^d]\|$\)" doppeld Doppel dd und noch ein Doppel dd_ende

Und diesmal hat es geklappt. Ich erweitere die Datei um zu sehen ob das "dd" auch am Zeilenanfang bzw. Zeilenende gefunden werden:

einfach d Doppel dd Dreifach ddd und noch ein Doppel dd_ende dd_ende anfang_dd

klaus@athlon:~/bin> grep "\(^\|[^d]\)d\{2\}\([^d]\|$\)" doppeld Doppel dd und noch ein Doppel dd_ende dd_ende anfang_dd

Und es funktioniert. An dem oben stehenden Beispiel sieht man dann auch, dass einige Erfahrung dazu gehört um komplexere Reguläre Ausdrücke zu bilden.

Im nächsten Beispiel werden, analog zum vorherigen Beispiel, Zeilen mit 2 Leerschritten gesucht.

Dies ist die Datei spaces. Die Datei enthält am Schluss auch eine Leerzeile:

dies ist ein space dies sind zwei spaces dies sind drei spaces dies sind nochmal zwei spaces

Und dies die Suche mit grep:

klaus@athlon:~/bin> grep "\(^\|[^[:space:]]\)[[:space:]]\{2\}\([^[:space:]]\|$\)" spacetest dies sind zwei spaces dies sind nochmal zwei spaces

grep in der Systemadministration:

Filtern eines bestimmten Prozesses:

klaus@athlon:~/bin> ps aux | grep kate klaus 7929 0.2 4.7 36712 24708 ? S 15:15 0:07 kate [kdeinit] kate klaus 8129 0.0 0.1 1884 728 pts/2 R+ 16:16 0:00 grep kate

Störend ist allerdings, dass der Prozess mit dem gesucht wird, auch noch im Ergebnis angezeigt wird. Diesen kann man dann so ausfiltern:

klaus@athlon:~/bin> ps aux | grep kate | grep -v grep klaus 7929 0.2 4.7 36712 24712 ? S 15:15 0:08 kate [kdeinit] kate

Die Suche nach einem bestimmten Paket, hier das Paket grep:

klaus@athlon:~/bin> rpm -qa | grep grep grep-2.5.1a-4

Diese Zeile filtert die Angaben zum nmb-Dämon aus der Ausgabe von /var/log/messages:

athlon:~ # tail -f -n 25 /var/log/messages | grep nmbd

Zum Seitenanfang

grep mit find kombinieren:

Da die rekursive Suche mit grep sehr begrenzt ist, wie oben bei der Option -r erläutert, kombiniert man für diesen Zweck die Befehle find und grep. find für die Dateisuche, grep für die Suche nach Regulären Ausdrücken innerhalb der gefundenen Dateien. find übergibt mit der Aktion -exec die gefundenen Dateien an grep zur Weiterverarbeitung:

find /etc -name "*" -exec grep -nsH "BOOT_" {} \;

  • find sucht ab dem Verzeichnis /etc nach allen Dateien ("*") und gibt die Dateiliste an grep weiter
  • grep sucht in allen Dateien nach "BOOT_"
  • -H    gibt die Dateinamen incl. Pfad mit aus
    -n    gibt die Zeilenummer der Textstelle an
    -s    unterdrückt Fehlermeldungen

Siehe auch: man 1 grep, info grep

Zum Seitenanfang

zgrep sucht in komprimierten Dateien unter Verwendung von grep

Ansonsten wird der Befehl genauso angewandt wie grep, deshalb erfolgt hier keine weitere Beschreibung.

Siehe auch: man 1 zgrep, info zgrep, man 1 grep, info grep

Zum Seitenanfang

Copyright, Nutzungsbedingungen, Haftungsausschluss

© Klaus Gerhardt • http://linuxseiten.kg-it.de

  • Dieses Dokument darf in unveränderter Form vervielfältigt und weitergereicht werden, sofern diese Nutzung privat erfolgt.
  • Der Name des Autors muss genannt werden, sowie die in diesem Absatz festgelegten Nutzungsbedingungen.
  • Eine kommerzielle Nutzung ist nur mit der Zustimmung des Autors erlaubt.
  • Die Vervielfältigung entsprechend den o.g. Bedingungen ist sowohl in elektronischer Form, als auch auf Papier zulässig.

Der Autor haftet weder für die Anwendung, der in diesem Dokument beschriebenen Verfahren, noch für die Anwendung von beigefügten Shell-Skripten. Die Haftung liegt alleine beim Anwender.

Shellskripte, die mit einem Link von diesem Dokument aus heruntergeladen werden können, bilden einen Teil dieses Dokumentes und müssen unverändert zusammen mit diesem Dokument weitergereicht werden. Man kann diese Shellskripte jedoch auch separat verwenden. Dann darf man sie nach belieben verändern.