GNU Grep


GNU Grep Basic Knowledge


Grep Grundlagen


Eingangs stellt sich nun erst einmal folgende wichtige Frage:
Wie gedenken Sie grep zu verwenden!


grep bietet Ihnen nämlich zwei ganz unterschiedliche Wege der Textanalyse!


Die nachfolgende Variante (Methode) prüft eine von Ihnen zuvor definierte (also angegebene) Datei auf das Vorkommen eines (von Ihnen vorgegebenen) Musters ...:


grep regexp filename



... so sucht grep also besagten regexp (Ausdruck bzw. Muster) in betreffender Datei (filename).

Die andere (zweite) Möglichkeit grep Texte analysieren zu lassen, besteht darin grep den Output (die Ausgabe) des Werkzeuges (Tool) cat als Eingabe (Input) an grep weiterzuleiten (also via "Pipe"); dies realisieren Sie wie nachstehend ersichtlich (dargestellt):


cat filename | grep regexp



Das Kommando (der Befehl) cat gibt also lediglich den Inhalt einer Ihm aufgetischten Datei aus. Der Output dieses Kommandos wird wiederum mittels "Pipe" an das Kommando grep gereicht, grep wird entsprechend des (von Ihnen bestimmten) Musters (Ausdruckes) nur jene Zeilen aus der Ausgabe (von cat) filtern, welche explizit (also exakt) mit besagter Regexp (Ausdruck / Muster) übereinstimmen.

Jene gerade genauestens erläuterten Beispiele führen somit zu absolut identischen Resultaten.

Was aber wenn Sie grep weder einen Dateinamen als Argument liefern geschweige denn Ihm entsprechenden Input (wie im cat-Beispiel) übergeben? Es ist ganz simpel, Sie tippen in Ihrer Konsole den Befehl grep gefolgt von einem Leerzeichen und einem entsprechendem Muster (Ausdruck), nun drücken Sie "Enter" ...

... und jetzt können Sie Ihren Audruck auf die gewünschte Funktionalität hin checken indem Sie in der Shell einen String (eine Zeichenkette) eingeben (welcher nach Ihrer Meinung vom Muster gefunden werden soll), sodann erneut die "Eingabetaste" drücken um daraufhin endlich nachzuschauen zu können ob das Terminal jenen String (Zeichenkette), welchen Sie eingegeben haben, von der Konsole wiederum ausgegeben wird (weil besagte Zeichenkette auf den Ausdruck (das Muster) passt).

Ist letzteres der Fall, so passt also jener von Ihnen eingetippte Text auf betreffendes Muster. Den grep-Befehl können Sie jetzt abbrechen in dem Sie z. B. einfach Strg-D drücken.

Es gibt Situationen wo der Output (die Ausgabe) derart umfangreich ausfällt dass es schwierig wird (bzw. ggf. unmöglich wird) in der Konsole bis zur ersten Zeile (der Ausgabe zurück) zu scrollen.

Bei sehr großen Dateien (wie (Fehler-)Log-Dateien) ist das (meist) der (absolute) (Regel-)Fall.

Das klügste wäre wohl in einem solchen Moment, wenn man die Shell anweist, den Output einfach seitenweise (also häppchenweise) aufzutischen; hierfür bedient man sich einfach der Kommandos less od. more ...

... im Klartext heißt das also, das man lediglich die Ausgabe von grep an den Befehl less resp. more weiterleitet. less bzw. more nimmt also den Output von grep als Input entgegen und tut sodann was es immer tut - jedweden Text SEITENWEISE anzuzeigen!


grep regexp filename | more



Es besteht überdies die Möglichkeit, den Output (die Ausgabe (resp. die Ergebnisse)) in eine Datei (mittels Eingabe- / Ausgabeumlenkung) umzuleiten; im Nachhinein können Sie diese dann via (Text-)Editor öffnen / bearbeiten:


grep regexp filename > newfilename



Das nachstehende Beispiel behandelt eine Textdatei namens editinginfo diese beinhaltet Datum, Benutzernamen sowie jene Datei, welche durch betreffenden Benutzer an betreffendem Datum editiert wurde.

Wenn also ein Administrator lediglich jene Dateien herausfiltern möchte, welche (z. B.) von "Smith" editiert wurden, so sei Ihnen untenstehendes Beispiel empfohlen:


cat editinginfo | grep Smith



Der entsprechende Output wäre somit der (hier) nachfolgende:


May 20, 2008 Smith hi.txt
June 21, 2008 Smith world.txt
.
.



Eventuell tendieren Sie auch dazu div. Muster (Ausdrücke) zu formulieren (verwenden); dies ließe sich über sog. "Verkettungen" von grep-Kommandos bewerkstelligen.

So könnte man beispielsweise auch anstelle von ...


cat filename | grep regexp



... od. ähnlichem, den Output von grep als Input an ein nachgelagertes grep-Kommando (Befehl) schicken; z. B. wie nachfolgend dargestellt:


cat filename | grep regexp | grep regexp2



Hier würde also das Kommando nach jenen Zeilen in der Datei filename Ausschau halten, welche regexp und auch regexp2 beinhalten. So sucht also der zweite grep-Befehl in den Resultaten des ersten grep-Befehls mit dem (Ausdruck / Muster) regexp2.

Das heißt also anders ausgedrückt dass (die Ausgabe von) cat an den ersten grep-Befehl (als Eingabe) übergeben und mit regexp (entsprechend) durchsucht wird, die hieraus folgenden Ergebnisse (der Output), werden also (wiederum als Input) an den zweiten (und letzten) grep-Befehl übergeben und jetzt mit regexp2 gefiltert (also auf das Vorkommen von entsprechenden Mustern durchsucht) - es folgt somit das Endergebnis.

Wenn man nun wissen möchte an welchen Tagen Smith eine Datei editiert hat, hiervon aber die Datei hi.txt ausnehmen möchten, so wäre nachstehendes Beispiel eine Möglichkeit genau dies zu tun:


cat editinginfo | grep Smith | grep -v hi.txt



Das Resultat wäre sodann das folgende:


June 21, 2008 Smith world.txt



In Bezug auf dass "Verketten" von grep-Kommandos ist noch erwähnenswert das dies allerdings eine meistens ineffiziente Methodik darstellt.

Denn oft kann schon ein einzelner regulärer Ausdruck bewirken, dass mehrere Bedingungen in einer Suche zusammengefasst werden. So könnte man also auch anstelle des vorstehenden Beispiels, welches drei Kommandos miteinander verknüpft, die gleiche Funtionalität mit diesem (nachstehendem) Snippet (Code) mit folgender Befehlsfolge erlangen:


grep Smith | grep -v hi.txt



Wie aus vorigen Beispielen bereits ersichtlich wird das Pipe-Zeichen genutzt, um einem nachgelagerten Kommando als ein Eingabe die Ausgabe des diesem vorgelagerten Befehls zu überreichen. Wie (obig) unschwer zu erkennen sein dürfte sucht grep also nach jenen Zeilen, welche (die Zeichenkette) "Smith" beinhalten und übergibt besagte Zeilen an den nächsten grep-Befehl, der jedoch Zeilen ausschließt, welche "hi.txt" beinhalten.

Die logische Schlussfolgerung muss also lauten dass wenn Sie es vermeiden können Befehle miteinander via Pipe zu verknüpfen sich das positiv auf die Performance auswirken kann; ergo würde sie (die Performance) im Allgemeinen effizienter sein.

Dies ist jedoch wohl eher bei größeren Dateien (im Gigabyte-Bereich) welche es zu durchsuchen gilt von Relevanz, der Performance-Gewinn beim Durchsuchen von kleinen Dateien ist nicht nennenswert (da subjektiv meist nicht bzw. kaum spürbar).

Trotzdem gibt es Situationen, in welchen das Verknüpfen von Kommandos (via Pipe) eine gute Idee ist:

Beispielsweise wenn Sie Inhalte durchsuchen möchten, welche kontinuierlich gestreamt werden. Angenommen es geht um eine Logdatei welche Sie in Echtzeit auf gewisse Inhalte hin überwachen möchten. Diesbezüglich würde sich nachfolgender Code anbieten:


tail -f /var/log/messages | grep WARNING



Dieses Kommando gibt die letzen zehn Zeilen aus der Datei /var/log/messages zurück. Da die Datei über vorstehenden Code offen gehalten wird, werden somit immer die aktuell letzten Zeilen ausgeben. Man kann der Datei quasi beim wachsen zusehen!

Die Option -f von tail bezeichnet man auch als "follow".

Die vorstehend behandelte Befehlskette sucht also nach Einträgen die die Zeichenkette "WARNING" beinhalten; diese werden sodann auf der Shell ausgegeben, alle anderen Mitteilungen jedoch verworfen.

Sobald grep bei seiner Suche einen Zeilenumbruch findet, wird die komplette Suche in der nachfolgenden Zeile neu gestartet. Wenn Sie mittels grep nach einem ganzem Satz suchen, so ist nicht unwarscheinlich, dass dieser Satz einen Zeilenumbruch beinhaltet; somit werden Sie den Satz nicht direkt als ganzen String finden können.

Auch die Angabe eines Zeilenendzeichens inmitten des Suchmusters löst die Problematik leider nicht. Manch ein (Text-)Editor resp. andere Anwendungen brechen Wörter (frecherweise) einfach um, ohne hierbei einen "harten" Zeilenumbruch einzufügen. Bei solchen "harten" Zeilenumbrüchen ist jene vorbeschriebene Suche allerdings kein Problem; aus diesem Grunde ist es um so interressanter diese Besonderheiten für sich auszunutzen!

Um mit den Details (der Implementierung) regulärer Ausdrücke auf (Ihrem Computer) vertraut zu werden, bedienen Sie sich einfach der Manpages regex bzw. re_format . Erwähnenswert ist zudem, dass leider nicht alle Funktionen / Fähigkeiten regulärer Ausdrücke in grep eingebaut sind. So können beispielsweise (jene von grep) gesuchte(n) (und gefunde(n)) Strings nicht (durch andere Zeichenketten ersetzt werden. Das ersetzen von Zeichenketten ist aber eine Spezialität des Befehls (Streameditors) sed ...!

Überdies sollten Sie immer im Hinterkopf behalten das grep einige hilfreiche Escape-Zeichen - allem Anschein nach - fehlen. Wie beispielsweise die Escape-Folge \d! Besagte Escape-Folge findet nämlich beliebige Ziffernzeichen (0 bis 9) (in einigen) regulären Ausdrücken. Scheinbar lässt sich besagtes "Feature" in den Standardistributionen von grep noch nicht einmal mit den normalen Kompilierungsoptionen entsprechend implementieren. Eine Ausnahme bildet hier allerdings grep im Perl-Stil!

Das Tool grep ist sozusagen ein Paket welches aus vier unterschiedlichen Programmen besteht; jedes Programm nutzt andere Varianten regulärer Ausdrücke (dies wirkt sich signifikant auf die Mustererkennung aus).

Jedes Mustererkennungssystem hat also seine Stärken aber auch seine Schwächen und jedes wird auf dieser Webseite eingehend beleuchtet.



Umgebungsvariablen (welche für grep relevant sind)


Umgebungsvariablen befähigen Sie, grep mit maximaler Effizienz zu nutzen!

Sie können beispielsweise das env Kommando - in der Konsole - aufrufen, wenn Sie jene aktuell gesetzten Parameter sichten möchten. Der Output besagten Befehls könnte sodann (in etwa) wie folgt aussehen:


$ env
USER=user
LOGNAME=user
HOME=/home/user
PATH=/usr/local/sbin:
/usr/local/bin:/usr/sbin:
/usr/bin:/sbin:/bin:
/usr/X11R6/bin

SHELL=/usr/local/bin/tcsh
OSTYPE=linux
LS_COLORS=no=0:fi=0:di=36:ln=33:
ex=32:bd=0:cd=0:pi=0:so=0:do=0:
or=31

VISUAL=vi
EDITOR=vi
MANPATH=/usr/local/man:/usr/man:
/usr/share/man:/usr/X11R6/man



Wenn Sie betreffende (Umgebungs-)Variablen (dauerhaft) auf neue Werte setzen möchten, so müssen nichts weiter tun als lediglich die Datei .profile (in Ihrem Home-Verzeichnis) entsprechend zu editieren. Augegangen vom obigem Output (Ausgabe), könnten Sie beispielsweise Ihren EDITOR von vi auf vim ändern (sofern Sie dies denn auch möchten).

Entsprechend vorbeschriebenem Vorschlag (Beispiel) könnten Sie in der Datei .profile nachstehenden Code ergänzend (bzw. ersetzend) eintragen:

setenv EDITOR vim

Gemäß vorstehendem Codes würde nun (für jede Session welche vorbeschriebene .profile-Datei ausliest) vim als (Standard-)Editor verwendet werden (und zwar dauerhaft).

grep ist ein sehr vielseitiges Werkzeug, da es dem Anwender so zahlreiche Möglichkeiten an die Hand gibt.

In Bezug auf Variablen gibt es (div.) spezielle Optionen, welche auf dieser Website noch eingehend erörtert werden. Was grep anbelangt fällt dieses auf das C Locale zurück, sofern die Variablen LC_foo, LC_ALL, LANG nicht gesetzt worden sind, der lokale Katalog nicht installiert ist od. aber auch der National Language Support (NLS) nicht einkompiliert ist.

Ein "Locale" ist die Konvention, welche verwendet wird, um in einer bestimmten Sprache zu interagieren. Wenn Sie die Variable LANG auf einen anderen Wert setzen, können Sie die Spracheinstellung Ihres Rechners ändern.

Sobald Ihr Computer bootet, setzt Ihr Computer jene Werte welche im Kernel abgelegt sind; diese Einstellungen lassen sich jedoch abändern. LC_ALL ist - im Übrigen - keine echte Variable, sondern bloß ein Makro, welches Ihnen erlaubt, die "Locale" für alle Zwecke zu setzen.

Locale-spezifische Einstellung können Sie (jeweils) mittels der "Variablen" LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY od. LC_TIME vornehmen (Aufzählung nicht abschließend).

Erwähnenswert ist in diesem Kontext das div. POSIX-Zeichenklassen genau davon abhängen, welches Locale gerade verwendet wird.

Auch PCRE greift stark auf vorbenannte Locale-Einstellungen zurück, insbesondere auf jene genutzten Zeichenklassen. Weil grep explizit darauf ausgelegt ist Text (also Strings) in Text- resp. Binärdateien zu suchen, ist die Art und Weise betreffender Sprachverarbeitung von gewisser Relevanz.

Oftmals reicht es allerdings vollkommen aus, wenn Sie die Locale-Einstellungen einfach auf den Standardwerten belassen. Sofern Sie jedoch entsprechende Änderungen vornehmen möchten, stellt dies selbstverständlich kein Problem dar.

Das Konzept der "Locales" dürfte Ihnen jetzt ausreichend vertraut sein; deshalb behandeln wir nun abschließend jene für grep relevanten Umgebungsvariablen:

GREP_OPTIONS
Vorstehende Variable überschreibt jene "einkompilierten" Standardoptionen (für grep). Diese (überschriebenen) (Standard-)Optionen werden dann (von grep) so interpretiert, als wären diese direkt via Kommandozeile eingegeben worden. Angenommen Sie möchten die grep-Option --binary-files so überschreiben dass diese auf den Wert text gesetzt wird ...

... so müssten Sie die Variable GREP_OPTIONS für die Option --binary-files mit dem Wert text versehen.

Somit besäße --binary-files nun den Wert text, ohne dass Sie hierfür explizit --binary-files=text notieren müssten. Trotzdem könnte --binary-files noch immer mit einem anderen Wert belegt werden; beispielsweise so --binary-files=without-match).

Diese Möglichkeit ist besonders praktisch beim schreiben von Skripten, bei welchen eine Reihe von "Standardoptionen" einmal in den Umgebungsvariablen notiert werden können und sodann nie mehr explizit aufgeführt werden müssen.

Allerdings gibt es einen kleinen Haken:
Jede Option, welche in GREP_OPTIONS gesetzt wird, wird dann so abgearbeitet, als wären diese direkt im Kommando grep angegeben worden. Das heißt also, dass die "echten" Kommandozeilenoptionen jene aus der Umgebungsvariable nicht überschreiben werden. Käme es aus diesem Grunde zu einem Konfliktfall, sähe ein (entsprechender) grep-Fehler evtl. wie nachstehend aus:


$ export GREP_OPTIONS=-E
$ grep -G '(red)' test
grep: conflicting matches specified



Man sollte gut überlegen, ob bzw. welche Optionen man in besagte Umgebungsvariable (GREP_OPTIONS) einträgt; am besten man setzt dortig nur jene Optionen welche auch immer genutzt werden sollen.

GREP_COLORS (od. GREP_COLOR für ältere Versionen)
Mit vorstehender Variable wird jener Farbwert bestimmt, welcher für das Hervorheben der passenden Muster verwendet werden soll. Diese (Variable resp. Ihr Wert) wird wiederum über die Option
--color[=WHEN ] aufgerufen, wobei WHEN die Werte never, auto od. always haben kann.

Was die Farbwert-Einstellungen anbelangt, so sollte es sich hierbei um eine Kombination aus zwei Zahlen handeln (siehe nachstehende Tabelle).


FarbeCodeFarbeCodeFarbeCodeFarbeCode
Schwarz0;30Dunkelgrau1;30Blau0;34Hellblau1;34
Grün0;32Hellgrün1;32Cyan0;36Helles Cyan1;36
Rot0;31Hellrot1;31Lila0;35Helllila1;35
Braun0;33Gelb1;33Hellgrau0;37Weiß1;37



Jene Farbwerte müssen syntaktisch korrekt notiert werden; betrachten Sie diesbzgl. nachfolgendes Beispiel:


export GREP_COLORS='ms=01;31:mc=01;31:
sl=:cx=:fn=35:ln=32:bn=32:se=36'



Wichtig ist vorallem dass Sie die (Umgebungs-)Variablen immer via export-Befehl exportieren (global verfügbar machen); auch wenn hierauf in div. Beispielen nicht immer explizit eingegangen wird ...

... denn es wird einfach davon ausgegangen das der Leser ein gewisses Grundwissen mitbringt.

Beginnt der notierte Farbwert jedoch mit 0 (wie beispielsweise hier 0;30, (dass entspricht der Farbe Schwarz)), ist es völlig ausreichend einfach bloß 30 für den Wert Schwarz anzugeben. Sofern Sie also keine neuen Farbwert-Einstellungen setzen, werden (von grep) weiterhin die Vorgabe-Einstellungen benutzt.

ms steht hierbei für "Matching String" (und somit z. B. für jenes Muster welches Sie eingeben).
mc steht wiederum für "Matching Context" (und demnach für Zeilen, welche mittels (der Option) -C ausgegeben werden).
Mit sl wird die Farbe der "Selected Lines" definiert (also die Farbe der ausgewählten Zeilen).
Durch cx wird die Farbe für den "Selected Context" (also den ausgewählten Kontext) festgelegt.
Mittels fn wird die Farbe für den "File Name" deklariert (sofern der Dateiname angezeigt werden soll).
Via ln wird der Farbwert für die "Line Numbers" bestimmt (also der Zeilennummer (sofern angezeigt)).
Per bn modifizieren Sie den Farbwert für "Byte Numbers" (also Byte-Werte, soweit angezeigt).
Und über se stellen Sie den Farbwert für "Separator Color" ein, (d. h. die Farbe des Seperators).

LC_ALL, LC_COLLATE, LANG
Diese Variablen müssen exakt in dieser Reihenfolge notiert werden und bestimmen somit folglich die Sortierreihenfolge od. die richtige Reihenfolge bei Bereichen. Hierbei könnte es sich beispielsweise um die korrekte Abfolge der Literale (Buchstaben) in einem Alphabet handeln.

LC_ALL, LC_CTYPE, LANG
Diese Variablen bestimmen wiederum LC_CTYPE od. den Typ der Zeichen, welche von grep genutzt werden. Durch diese Methodik wird (z. B.) bestimmt, welche Zeichen nun Whitespaces sind bzw. welche wiederum ein Form Feed, etc.!

LC_ALL, LC_MESSAGES, LANG
Mit diesen Variablen bestimmen Sie das MESSAGES-Locale und die jeweilige Sprache, welche grep für seine Mitteilungen benutzen soll. Im Zweifel würde grep auf das Standard-Locale C zurückfallen; was demnach US-Englisch entspricht.

POSIXLY_CORRECT
Ist diese Variable gesetzt, befolgt grep die POSIX.2-Anforderungen, welche festlegen, dass all jene Optionen, welche auf Dateinamen folgen, wiederum selbst als Dateinamen behandelt werden sollen.

Ist POSIXLY_CORRECT nicht gesetzt würden diese Optionen einfach so abgearbeitet (interpretiert) werden, als "wären" diese (wie üblich) "vor" den Dateinamen notiert worden. Das heißt also die Optionen würden auch als soche erkannt werden. Wenn POSIXLY_CORRECT allerdings gesetzt wurde, so würde ein grep -E string filename -C 3 (beispielsweise) ein "-C 3" als Dateinamen werten (obschon es als Option gedacht war).

Überdies wird in POSIX.2 bestimmt, dass alle nicht erkannten Optionen als "illegal" gekennzeichnet werden - per Standard werden diese unter GNU grep als "ungültig" angesehen (erachtet).



GNU Grep Manual Page


Bezeichnung


grep
egrep
fgrep
rgrep

Geben Zeilen aus, welche zu einem Suchmuster passen.




Übersicht


grep [OPTIONEN] MUSTER [DATEI...]
grep [OPTIONEN] [-e MUSTER | -f DATEI] [DATEI...]



Beschreibung


grep sucht in den angegebenen DATEIen (od. der Standardeingabe, wenn keine Dateien oder ein einzelner Trenn-/Bindestrich (-) als Dateiname angegeben wurde) nach Zeilen, die auf das MUSTER passen.

Per Voreinstellung gibt grep die passenden Zeilen aus.

Darüber hinaus stehen die drei Programmvarianten egrep, fgrep und rgrep zur Verfügung. Sie entsprechen den Aufrufen grep -E, grep -F und grep -r.

Von dem direkten Aufruf entweder als egrep od. fgrep wird abgeraten.
Die Programme werden bereitgestellt, damit historische Anwendungen, die sich auf deren Existenz verlassen, ohne Modifikation laufen können.



O P T I O N E N


Allgemeine Programminformationen


--help
grep zeigt eine kurze Zusammenfassung der Befehlszeilen-Optionen und die Adresse für Fehlerberichte an; anschließend wird es beendet.

-V, --version
grep zeigt die Versionsnummer auf der Standardfehlerausgabe an. Die Versionsnummer sollte in allen Fehlerberichten (siehe unten) mit angegeben werden.



Wahl des Musters


-E, --extended-regexp
MUSTER soll als erweiterter regulärer Ausdruck (extended regular expression, ERE, siehe unten) interpretiert werden. (-E wird von POSIX gefordert.)

-F, --fixed-strings
Interpretiert MUSTER als Liste feststehender Zeichenketten, die durch Zeilenumbruch getrennt sind. Für einen Treffer muss mindestens eine der Zeichenketten passen. (-F wird von POSIX gefordert.)

-G, --basic-regexp
Interpretiert MUSTER als gewöhnlichen regulären Ausdruck (basic regular expression, BRE, siehe unten). Das ist die Voreinstellung.

-P, --perl-regexp
Interpretiert MUSTER als einen regulären Perl-Ausdruck. Diese Option ist höchst experimentell.

Es kann vorkommen, dass grep -P wegen nicht implementierter Features warnt.



Steuerung des Abgleichs


-e MUSTER, --regexp=MUSTER
Verwendet MUSTER als das Suchmuster. Damit können mehrere Suchmuster angegeben oder Muster geschützt werden, die mit einem Bindestrich (-) anfangen. (-e wird von POSIX gefordert.)

-f DATEI, --file=DATEI
Liest die Suchmuster Zeile für Zeile aus DATEI ein. Eine leere Datei enthält keine Suchmuster und erzielt deshalb auch keine Treffer. (-f wird von POSIX gefordert.)

-i, --ignore-case
Unterscheidet auf der Suche nach Treffern sowohl im MUSTER als auch in den Eingabedateien nicht zwischen Groß- und Kleinschreibung. (-i wird von POSIX gefordert.)

-v, --invert-match
Invertiert das Suchmuster, so dass alle Zeilen ausgewählt werden, die nicht auf MUSTER passen. (-v wird von POSIX gefordert.)

-w, --word-regexp
Wählt nur solche Zeilen aus, deren Treffer aus vollständigen Wörtern bestehen. Im Einzelnen verläuft der Test so, dass eine passende Zeichenkette entweder am Zeilenanfang beginnen muss oder auf ein Zeichen folgt, das nicht zu den Wortaufbau-Zeichen gehört.

Ebenso muss das Ende der Zeichenkette entweder mit dem Zeilenende zusammenfallen oder es darf kein Wortaufbau-Zeichen folgen. Wortaufbau-Zeichen sind alle Buchstaben, Ziffern sowie der Unterstrich.

-x, --line-regexp
Wählt nur solche Zeilen aus, deren Treffer die komplette Zeile umfasst. (-x wird von POSIX gefordert.) -y veraltetes Synonym für -i



Allgemeine Ausgabesteuerung


-c, --count
Statt die passenden Zeilen direkt anzuzeigen, wird lediglich ihre Anzahl pro Eingabedatei ausgegeben. Ist zusätzlich die Option -v, --invert-match (siehe unten) angegeben, zählt grep die Zeilen ohne Treffer.

--color[=WANN], --colour[=WANN]
Schließt die gefundenen (nicht leeren) Zeichenketten, passenden Zeilen, Kontextzeilen, Dateinamen, Zeilennummern, Byte-Offsets und Separatoren (für Felder und Gruppen von Kontextzeilen) mit Escape-Sequenzen ein, damit diese auf dem Terminal farbig angezeigt werden.

Die Farben werden durch die Umgebungsvariable GREP_COLORS definiert. Die missbilligte Umgebungsvariable GREP_COLOR wird weiterhin unterstützt, hat aber keine Priorität und sollte nicht verwendet werden. WANN kann die Werte never, always od. auto annehmen.

-L, --files-without-match
Statt der normalen Ausgabe wird der Name jeder Datei ohne Treffer angezeigt. Die Suche endet beim ersten Treffer.

-l, --files-with-matches
Statt der normalen Ausgabe wird der Name jeder Datei mit mindestens einem Treffer angezeigt. Die Suche endet beim ersten Treffer. (-l wird von POSIX gefordert.)

-m ZAHL, --max-count=ZAHL
Beendet das Lesen einer Datei, nachdem ZAHL passende Zeilen gefunden wurden. Wenn die Eingabe aus einer regulären Datei stammt und ZAHL passende Zeilen ausgegeben wurden, positioniert grep, bevor es endet, die Standardeingabe ungeachtet der Existenz folgender Kontextzeilen direkt hinter der letzten passenden Zeile.

Dies ermöglicht einem aufrufenden Prozess die Fortsetzung der Suche. Wenn grep nach ZAHL passenden Zeilen endet, gibt es alle nachfolgenden Kontextzeilen aus. Wenn außerdem die Option -c (od. --count) verwendet wird, gibt grep als Ergebnis keine Zahl aus, die größer ist als ZAHL.

Wenn die Option -v (--invert-match) verwendet wird, endet grep nach der Ausgabe von ZAHL nicht passenden Zeilen.

-o, --only-matching
Anstatt der gesamten Zeile werden nur die passenden (nicht leeren) Teile ausgegeben. Jeder dieser Teile wird auf einer eigenen Zeile ausgegeben.

-q, --quiet, --silent
Unterdrückt die normalen Ausgaben. Die Suche endet sofort nach dem ersten Treffer und gibt auch beim Auftreten von Fehlern den Status Null zurück. Lesen Sie auch die Beschreibung der Option -s od. --no-messages. (-q wird von POSIX gefordert.)

-s, --no-messages
Unterdrückt Fehlermeldungen über nicht vorhandene oder nicht lesbare Dateien.

Anmerkung zur Portierbarkeit: Im Gegensatz zu GNU grep war das ursprüngliche (7th Edition Unix) grep nicht POSIX-konform, da ihm die Option -q fehlte und die Option -s sich so verhielt wie -q im heutigen GNU grep.

grep im USG-Stil fehlte ebenfalls -q, aber seine Option -s verhielt sich wie GNU grep. Portable Shell-Skripte, die auch mit dem ursprünglichen grep funktionieren müssen, sollten deshalb weder -q noch -s verwenden und stattdessen die Ausgabe (stdout und stderr) nach /dev/null umleiten. (-s wird von POSIX gefordert.)



Präfix-Festlegung der Ausgabezeilen


-b, --byte-offset
Gibt vor jeder Ausgabezeile die Byte-Position in der Datei relativ zum Dateianfang (0) an. Wenn -o (--only-matching) angegeben wird, wird die Position des gefundenen Teils angezeigt.

-H, --with-filename
Gibt vor jedem Treffer den zugehörigen Dateinamen aus. Das ist das Standardverhalten, wenn mehr als eine Datei untersucht wird.

-h, --no-filename
Der Dateiname wird vor einem Treffer nicht ausgegeben. Das ist das Standardverhalten bei der Suche in nur einer Datei (od. nur in der Standardeingabe).

--label=TEXT
Zeigt tatsächlich aus der Standardeingabe gelesene Eingaben an, als seien sie aus Datei TEXT gelesen. Das ist besonders praktisch für die Realisierung von Werkzeugen wie zgrep, z.B.:


gzip -cd foo.gz | grep --label=foo -H



irgendwas (siehe auch die Option -H).

-n, --line-number
Gibt vor jeder Zeile die Zeilennummer (gezählt ab 1) innerhalb der aktuellen Eingabedatei aus. (-n wird von POSIX gefordert.)

-T, --initial-tab
Stellt sicher, dass das erste Zeichen des eigentlichen Zeileninhalts auf einem Tabulatorstopp liegt, so dass die Ausrichtung der Tabulatoren normal aussieht. Dies ist sinnvoll für die Optionen, die ihrer Ausgabe einen Präfix voranstellen: -H, -n und -b. Um die Wahrscheinlichkeit zu vergrößern, dass die Zeilen aus einer einzelnen Datei alle in der gleichen Spalte beginnen, bewirkt diese Option auch, dass (eventuell vorhandene) Zeilennummern und Byte-Offsets mit minimaler Feldgröße ausgegeben werden.

-u, --unix-byte-offsets
Zeigt die Byte-Positionen im Unix-Stil an. Mit Hilfe dieses Schalters gibt grep Byte-Positionen in Textdateien stets so aus, als würden sie nur ein einzelnes Zeilenumbruchsymbol am Zeilenende enthalten: Ein eventuelles Wagenrücklaufsymbol am Zeilenende wird nicht berücksichtigt. So erzeugt grep die gleichen Resultate wie auf einer UNIX-Maschine. Diese Option ist nur in Verbindung mit dem Schalter -b wirksam. Auf anderen Plattformen als MS-DOS und MS-Windows hat sie keine Auswirkung.

-Z, --null
Gibt statt des üblichen Trennzeichens nach jedem Dateinamen ein Nullbyte (das ASCII-Zeichen NUL) aus. So gibt beispielsweise grep -lZ nach jedem Dateinamen statt des gebräuchlichen Zeilenumbruchs ein Null-Byte aus.

Mit dieser Option bleibt die Ausgabe selbst bei ungewöhnlichen Dateinamen, die beispielsweise einen Zeilenumbruch enthalten, eindeutig. Diese Option kann zusammen mit Befehlen wie find print -0, perl -0, sort -z und xargs -0 zur Verarbeitung beliebiger Dateinamen verwendet werden (auch solche, die Zeilenumbrüche enthalten).



Steuerung der Kontextzeilen


-A ZAHL, --after-context=ZAHL
Zeigt ZAHL Kontextzeilen im Anschluss an eine auf das Muster passende Zeile an. Gibt eine Zeile mit einem Gruppentrennzeichen (--) zwischen benachbarten Gruppen von Treffern aus.

Zusammen mit der Option -o od. --only-matching hat diese Option keine Auswirkung und es wird eine Warnung ausgegeben.

-B ZAHL, --before-context=ZAHL
Zeigt ZAHL Kontextzeilen vor einer auf das Muster passenden Zeile an. Gibt eine Zeile mit einem Gruppentrennzeichen (--) zwischen benachbarten Gruppen von Treffern aus.

Zusammen mit der Option -o od. --only-matching hat auch diese Option ebenso keine Auswirkung und es wird eine Warnung ausgegeben.

-C [ZAHL], -ZAHL, --context[=ZAHL]
Zeigt je ZAHL Kontextzeilen vor und nach einer auf das Muster passenden Zeile an. Gibt eine Zeile mit einem Gruppentrennzeichen (--) zwischen benachbarten Gruppen von Treffern aus.

Zusammen mit der Option -o od. --only-matching hat besagte Option abermals keine Auswirkung und es wird eine Warnung ausgegeben.



Auswahl von Dateien und Verzeichnissen


-a, --text
Verarbeitet eine Binärdatei, als wäre sie gewöhnlicher Text; dieser Schalter ist gleichwertig mit --binary-files=text.

--binary-files=TYP
Falls die ersten Bytes einer Datei anzeigen, dass sie Binärdaten enthält, soll angenommen werden, dass es sich um eine Datei vom Typ TYP handelt. Als Standard wird für den TYP binary angenommen.

Normalerweise gibt grep lediglich eine Meldung aus, dass es in einer binären Datei Treffer gab, und schweigt, wenn nichts gefunden wurde. In der Einstellung without-match überspringt grep Binärdateien, ohne dort nach Treffern zu suchen.

Der Schalter -I bewirkt dasselbe. Mit der Einstellung text (äquivalent mit -a) bearbeitet grep eine Binärdatei als sei sie eine Textdatei.

Warnung:
grep --binary-files=text kann mit üblen Nebenwirkungen binären »Müll« ausgeben, wenn die Ausgabe auf eine Konsole geleitet wird und deren Treiber manche der Binärdaten als Steuerzeichen interpretiert.

-D AKTION, --devices=AKTION
Wenn die Eingabedatei ein Gerät, ein FIFO od. ein Socket ist, wird sie mit AKTION verarbeitet. Die Standard-AKTION ist read.

Das bedeutet, dass Geräte wie eine gewöhnliche Datei gelesen werden. Mit der AKTION skip werden Geräte stillschweigend ausgelassen.

-d AKTION, --directories=AKTION
Ist eine Eingabedatei ein Verzeichnis, wird es mit der AKTION verarbeitet. In der Standardeinstellung read liest grep das Verzeichnis wie eine gewöhnliche Datei ein. Ist AKTION auf skip gesetzt, so werden Verzeichnisse stillschweigend übersprungen.

Steht AKTION auf recurse od. wurde der Schalter -r benutzt, so durchsucht grep rekursiv sämtliche Dateien unterhalb jedes Verzeichnisses.

--exclude=GLOB
Überspringt Dateien, deren Dateiname unter Verwendung von Platzhaltern zu GLOB passt. Ein Dateinamen-GLOB kann *, ? und [...] als Platzhalter und \ zum Maskieren von Platzhalterzeichen oder des Rückschrägstriches verwenden.

--exclude-from=DATEI
Überspringt Dateien, deren Dateinamen zu einem (mittels Platzhalter-Abgleich wie unter --exclude beschrieben) aus DATEI gelesenen Dateinamen-GLOB passen.

--exclude-dir=VERZ
Schließt Verzeichnisse, die zum Muster VERZ passen, von der rekursiven Suche aus. -I Behandelt Binärdateien so, als würde ihr Inhalt nie auf das Suchmuster passen. Dies ist gleichbedeutend mit der Option --binary-files=without-match.

--include=GLOB
Durchsucht nur Dateien, deren "base names" zu (mittels Platzhalter-Abgleich wie unter --exclude beschrieben) GLOB passen.

-R, -r, --recursive
Durchsucht rekursiv sämtliche Dateien unterhalb eines Verzeichnisses. Die Option -drecurse hat dieselbe Bedeutung.



Weitere Optionen


--line-buffered
Verwendet bei der Ausgabe Zeilenpuffer. Das kann Leistungseinbußen bewirken.

--mmap
Verwendet, falls möglich, beim Lesen der Eingabedaten den Systemaufruf mmap(2) statt des üblichen read(2). Unter gewissen Umständen erzielt --mmap bessere Leistungswerte, ist jedoch unzuverlässiger und kann sogar zu Programmabstürzen (inclusive core dumps) führen, wenn beispielsweise eine Eingabedatei während der Suche verkleinert wird oder ein Ein-/Ausgabefehler auftritt.

-U, --binary
Verarbeitet die Datei(en) als Binärdaten. Unter MS-DOS und MS-Windows versucht grep, den Dateityp zu bestimmen, indem es die ersten 32 kByte der Datei untersucht. In einer von grep zu einer Textdatei erklärten Datei entfernt es intern alle Wagenrücklaufzeichen (CR), damit ^ und $ in regulären Ausdrücken korrekt funktionieren.

Die Angabe von -U umgeht die ganze Raterei und weist grep an, jede Datei exakt so zu verarbeiten, wie sie eingelesen wurde. Falls es sich um eine Textdatei handelt, deren Zeilen mit einem kombinierten Wagenrücklauf und Zeilenumbruch (CR/LF) enden, arbeiten manche reguläre Ausdrücke fehlerhaft. Diese Option hat auf anderen Plattformen als MS-DOS und MS-Windows keine Auswirkungen.

-z, --null-data
Behandelt die Eingabe als einen Satz von Zeilen, von denen jede mit einem Null-Byte (das ASCII-Zeichen NUL) anstelle eines Zeilenvorschubs endet. Wie die Optionen -Z od. --null kann diese Option zusammen mit Befehlen wie sort -z für die Verarbeitung beliebiger Dateinamen eingesetzt werden.




Reguläre Ausdrücke


Unter einem regulären Ausdruck versteht man ein Muster, das eine Menge von Zeichenketten beschreibt. Reguläre Ausdrücke werden analog zu arithmetischen Ausdrücken aufgebaut: Sie werden mit Hilfe verschiedener Operatoren aus kleineren Ausdrücken zusammengesetzt.

grep versteht drei verschiedene Klassen regulärer Ausdrücke: "gewöhnliche" (basic, BRE), "erweiterte" (extended, ERE) und perl (PRCE). GNU grep stellt für gewöhnliche und erweiterte reguläre Ausdrücke die gleiche Funktionalität bereit.

In anderen Implementierungen steht mit gewöhnlichen regulären Ausdrücken jedoch nur ein eingeschränkter Funktionsumfang zur Verfügung. Die folgende Beschreibung bezieht sich auf erweiterte reguläre Ausdrücke; die Unterschiede zu gewöhnlichen regulären Ausdrücken werden im Anschluss daran zusammengefasst.

Die PRCE-Ausdrücke stellen zusätzliche Funktionen bereit und sind in pcresyntax (3) und pcrepattern (3) dokumentiert, sind aber möglicherweise nicht auf jedem System verfügbar.

Grundlegende Bausteine sind die regulären Ausdrücke, die auf ein einzelnes Zeichen passen. Die meisten Zeichen, insbesondere alle Buchstaben und Ziffern, sind zugleich reguläre Ausdrücke, die auf sich selbst passen. Alle Metazeichen, die eine besondere Bedeutung besitzen, können durch einen vorangestellten Rückschrägstrich geschützt werden.

Der Punkt . steht für jedes einzelne Zeichen.



Zeichenklassen und Klammerausdrücke


Ein Klammerausdruck ist eine durch [ und ] eingeschlossene Liste von Zeichen. Er passt auf jedes Zeichen aus der Liste. Beginnt die Liste mit dem Symbol ^, so passt der Ausdruck auf alle Zeichen, die nicht in der Liste enthalten sind.

Beispielsweise passt der reguläre Ausdruck [0123456789] auf eine beliebige einzelne Ziffer.

Innerhalb eines Klammerausdrucks sind Bereichsausdrücke (range expressions) möglich. Ein Bereichsausdruck besteht aus zwei durch einen Bindestrich getrennten Zeichen. Er steht für ein einzelnes Zeichen einschließlich der Begrenzungszeichen, das gemäß der Sortierreihenfolge der Locale und dem Zeichensatz zwischen den beiden Begrenzungszeichen liegt.

Zum Beispiel ist in der Standard-Locale C [a-d] äquivalent zu [abcd]. Viele Locales sortieren Zeichen in der Wörterbuch-Reihenfolge.

Dort ist [a-d] in der Regel nicht gleichwertig mit [abcd]; es wäre zum Beispiel gleichbedeutend mit [aBbCcDd]. Um die traditionelle Interpretation von Klammerausdrücken zu bewirken, können Sie die C-Locale verwenden. Dazu setzen Sie die Umgebungsvariable LC_ALL auf den Wert C.

Schließlich gibt es noch einige vordefinierte Zeichenklassen innerhalb von Klammerausdrücken mit (im Englischen) selbsterklärenden Namen. Das sind im Einzelnen:

[:alnum:] (Buchstaben und Ziffern),
[:alpha:] (Buchstaben),
[:cntrl:] (Steuerzeichen),
[:digit:] (Ziffern),
[:graph:] (graphische Zeichen, das heißt [:alnum:] und [:punct:]),
[:lower:] (Kleinbuchstaben),
[:print:] (druckbare Zeichen),
[:punct:] (Satzzeichen),
[:space:] (Leerraum),
[:upper:] (Großbuchstaben) und
[:xdigit:] (Ziffern des Hexadezimalsystems).

So bedeutet beispielsweise [[:alnum:]] die Zeichenklasse der Ziffern und Buchstaben in der aktuellen Locale. In der C-Locale und der Zeichenkodierung ASCII ist dies dasselbe wie [0-9A-Za-z].

(Beachten Sie, dass die eckigen Klammern Teil des symbolischen Namens der einzelnen Klassen sind. Zusätzlich dazu müssen noch die eckigen Klammern angegeben werden, die eine Liste von Zeichen begrenzen.)

Die meisten Metazeichen verlieren innerhalb eines Klammerausdrucks ihre besondere Bedeutung. Um ein ] selbst zu beschreiben, muss es an erster Stelle der Kette gesetzt werden. Soll ^ als gewöhnliches Zeichen auftreten, darf es nicht an erster Stelle stehen. Das Zeichen - selbst muss an letzter Stelle der Kette auftauchen.



Setzen von Ankern


Die Metazeichen Dach ^ und Dollar $ passen auf die leere Zeichenkette am Anfang beziehungsweise Ende einer Zeile.



Das Backslash-Zeichen (Rückschrägstrich) und spezielle Ausdrücke


Ganz ähnlich passen die Symbole \< und \> auf die leere Zeichenkette am Anfang beziehungsweise Ende eines Wortes. Das Symbol \b passt auf die leere Zeichenkette an einem Wortrand; \B bezeichnet das Gegenteil davon und passt auf die leere Zeichenkette, falls die sich nicht an einem Wortrand befindet.

Das Symbol \w ist ein Synonym für [_[:alnum:]] und \W steht für [^_[:alnum:]].



Wiederholungen


Einem regulären Ausdruck können ein oder mehrere Wiederholungsoperatoren folgen:

?
Das vorhergehende Objekt ist optional und tritt höchstens einmal auf.

*
Das vorhergehende Objekt tritt kein Mal oder beliebig oft auf.

+
Das vorhergehende Objekt tritt ein- od. mehrmals auf.

{n}
Das vorhergehende Objekt tritt genau n-mal auf.

{n,}
Das vorhergehende Objekt tritt n-mal oder öfter auf.

{n,m}
Das vorhergehende Objekt tritt mindestens n und höchstens m-mal auf.



Verknüpfung


Zwei reguläre Ausdrücke können verbunden werden. Der entstehende reguläre Ausdruck passt auf jede Zeichenkette, die aus zwei aneinander gesetzten Teilketten, die auf die zugehörigen Teilausdrücke passen, besteht.



Alternativen


Sind zwei reguläre Ausdrücke durch den Infix-Operator | verbunden, so passt der gesamte reguläre Ausdruck auf jede Zeichenkette, die auf einen der beiden Teilausdrücke passt.



Priorität


Wiederholungsoperatoren besitzen höhere Priorität als eine Aneinanderreihung. Am niedrigsten ist die Priorität der Alternative. Teilausdrücke können in Klammern gesetzt werden, um diese Regeln explizit abzuändern.



Rückwärtsverweise und Teilausdrücke


Die Rückwärtsreferenz \n - wobei n für eine einzelne Ziffer steht - steht für die Zeichenkette, die wiederum auf den vorhergehenden, eingeklammerten Teilausdruck Nummer n des regulären Ausdrucks passt.



Vergleich gewöhnlicher und erweiterter regulärer Ausdrücke


In gewöhnlichen regulären Ausdrücken besitzen die Metazeichen ?, +, {, }, |, ( und ) keine besondere Bedeutung.

Stattdessen müssen die mit einem Rückschrägstrich geschützten Versionen \?, \+, \{, \}, \|, \( und \) verwendet werden.

Das Metazeichen { wurde im ursprünglichen egrep nicht unterstützt. Andere Implementierungen unterstützen stattdessen \{, sodass Sie portable Skripte { in Mustern für grep -E generell vermeiden sollten. Für das Zeichen { selbst sollte der Ausdruck [{] verwendet werden.

GNU egrep versucht, das ursprüngliche Verhalten zu unterstützen indem es annimmt, dass { keine besondere Bedeutung besitzt, wenn es eine ungültige Intervallbeschreibung einleitet. So sucht beispielsweise der Befehl egrep '{1' nach der zwei Zeichen langen Zeichenkette {1 statt einen fehlerhaften regulären Ausdruck zu melden.

Dieses Verhalten ist in POSIX.2 als Erweiterung erlaubt. Portable Skripte sollten dieses Konstrukt nicht verwenden.



Umgebungsvariablen


Das Verhalten von grep wird durch die folgenden Umgebungsvariablen bestimmt.

Die Locale für die Kategorie LC_foo wird durch die Untersuchung der drei Umgebungsvariablen LC_ALL, LC_foo und LANG (in dieser Reihenfolge) bestimmt.

Die erste dieser Variablen, die gesetzt ist, legt die Locale fest. Ist beispielsweise LC_ALL nicht, dafür aber LC_MESSAGES auf pt_BR gesetzt, dann wird für die Kategorie LC_MESSAGES brasilianisches Portugiesisch verwendet. Die C-Locale wird verwendet, wenn keine dieser Umgebungsvariablen gesetzt ist, wenn der Locale-Katalog nicht installiert ist oder wenn grep ohne Unterstützung für Landessprachen (national language support, NLS) kompiliert wurde.

GREP_OPTIONS
Mit Hilfe dieser Variable lassen sich Standardoptionen definieren, die vor alle explizit angegebenen Optionen gesetzt werden. Enthält GREP_OPTIONS beispielsweise '--binary-files=without-match --directories=skip', so verhält sich grep, als ob die beiden Optionen --binary-files=without-match und --directories=skip auf der Befehlszeile vor allen weiteren Optionen angegeben worden wären. Mehrere Optionen werden durch Leerzeichen getrennt.

Ein Rückschrägstrich (backslash) schützt das folgende Zeichen, so dass auch Optionen angegeben werden können, die selbst Leerzeichen oder Rückschrägstriche enthalten.

GREP_COLOR
Diese Variable legt die Farbe fest, mit der (nicht leere) Fundstellen des Suchausdrucks hervorgehoben werden. Sie ist veraltet, wird aber immer noch unterstützt. Verwenden Sie stattdessen GREP_COLORS.

Die Fähigkeiten mt, ms und mc von GREP_COLORS werden dieser Variable im Konfliktfall vorgezogen. Die Variable kann nur die Farbe festlegen, mit der passender nicht leerer Text in jeder Zeile mit einer Fundstelle markiert wird (das ist eine ausgewählte Zeile, wenn die Befehlszeilenoption -v weggelassen wird, od. eine Kontextzeile, wenn -v angegeben ist). Der Standardwert ist 01;31. Er bedeutet roten Text in Fettdruck vor dem Standard-Hintergrund des Terminals.

GREP_COLORS
Gibt die Farben und andere Attribute an, die für Markierung verschiedener Elemente der Ausgabe verwendet werden. Ihr Wert ist eine durch Doppelpunkte getrennte Liste von Fähigkeiten, deren Standardwert gleich ms=01;31:mc=01;31:sl=:cx=:
fn=35:ln=32:bn=32:se=36
ist. (Die booleschen Fähigkeiten rv und ne sind also weggelassen (d.h. auf auf false gesetzt)). Es werden die folgenden Fähigkeiten unterstützt.

sl=
SGR-Teilsequenz für ganze ausgewählte Zeilen (d.h. übereinstimmende Zeilen, wenn die Befehlszeilenoption -v weggelassen wird oder nicht übereinstimmende Zeilen, wenn -v angegeben wird). Wenn jedoch sowohl die boolesche Fähigkeit rv als auch die Befehlszeilenoption -v angegeben werden, gilt die Option stattdessen für passende Kontextzeilen. Der Standardwert ist leer (d.h. das Standard-Farbpaar des Terminals).

cx=
SGR-Teilsequenz für ganze Kontextzeilen (d.h. nicht übereinstimmende Zeilen, wenn die Befehlszeilenoption -v weggelassen wird oder übereinstimmende Zeilen, wenn -v angegeben wird). Wenn jedoch sowohl die boolesche Fähigkeit rv als auch die Befehlszeilenoption -v angegeben werden, gilt die Option stattdessen für nicht passende Zeilen. Der Standardwert ist leer (d.h. das Standard-Farbpaar des Terminals).

rv
Boolescher Wert, der die Bedeutung der Fähigkeiten sl= und cx= vertauscht, wenn die Befehlszeilenoption -v gewählt wird. Der Standardwert ist false (d.h. die Fähigkeit wird nicht genutzt).

mt=01;31
SGR-Teilsequenz für passenden, nicht leeren Text in jeder passenden Zeile (d.h. einer ausgewählten Zeile, wenn die Befehlszeilenoption -v weggelassen wird oder einer Kontextzeile, wenn -v angegeben wurde). Die Wahl dieser Option ist gleichwertig mit der Wahl des gleichen Wertes für ms= und mc=. Der Standardwert ist fetter roter Text vor der aktuellen Hintergrundfarbe der Zeile.

ms=01;31
SGR-Teilsequenz für passenden, nicht leeren Text in einer ausgewählten Zeile. (Dies wird nur verwendet, wenn die Befehlszeilenoption -v weggelassen wird.) Die Wirkung der Fähigkeit sl= (od. cx=, wenn rv gesetzt ist) bleibt aktiv, wenn diese auftritt. Der Standardwert ist ein fetter roter Text vor dem aktuellen Zeilenhintergrund.

mc=01;31
SGR-Teilsequenz für passenden, nicht leeren Text in einer Kontextzeile. (Dies wird nur verwendet, wenn die Befehlszeilenoption -v gewählt wird.) Die Wirkung der Fähigkeit sl= (od. cx=, wenn rv gesetzt ist) bleibt aktiv, wenn diese »kicks in«. Der Standardwert ist ein fetter roter Text vor dem aktuellen Zeilenhintergrund.

fn=35
SGR-Teilsequenz für Dateinamen, die beliebigen Kontextzeilen vorausgehen. Standard ist ein violetter Textvordergrund vor dem Standardhintergrund des Terminals.

ln=32
SGR-Teilsequenz für Zeilennummern, die beliebigen Kontextzeilen vorausgehen. Standard ist ein grüner Textvordergrund vor dem Standardhintergrund des Terminals.

bn=32
SGR-Teilsequenz für »Byte Offsets«, die beliebigen Kontextzeilen vorausgehen. Standard ist ein grüner Textvordergrund vor dem Standardhintergrund des Terminals.

se=36
SGR-Teilsequenz für Separatoren, die zwischen die Felder für ausgewählte Zeilen (:), für Kontextzeilen (-) und zwischen Gruppen von benachbarten Zeilen (wenn ein von Null verschiedener Kontext gewählt wurde (--)) eingefügt werden. Der Standardwert ist ein blaugrüner (cyan) Textvordergrund vor dem Standardhintergrund des Terminals.

ne
Boolescher Wert, der das Löschen bis zum Zeilenende mittels »Erase in Line (EL) to Right« (\33[K) verhindert, wenn ein eingefärbtes Element endet. Er wird für Terminals benötigt, die EL nicht unterstützten. Ansonsten ist er nützlich für Terminals, für die die boolesche Terminfo-Fähigkeit back_color_erase (bce) nicht gilt, wenn die gewählten Markierungsfarben nicht den Hintergrund beeinflussen oder wenn EL zu langsam ist oder zu viel Flackern verursacht. Der Standardwert ist false (d.h. die Fähigkeit wird weggelassen).

Beachten Sie, dass boolesche Fähigkeiten keinen =-Teil aufweisen. Sie werden per Vorgabe weggelassen (d.h. auf false gesetzt) und werden aktiviert, wenn sie angegeben werden.

Im Abschnitt »Wahl der grafischen Darstellung« (Select Graphic Rendition, SGR) der Dokumentation des Textterminals finden Sie zulässige Werte und ihre Bedeutung als Zeichenattribute. Diese Teilzeichenkettenwerte sind ganze Zahlen in Dezimaldarstellung und können mit einem Semikolon verbunden werden. grep erzeugt aus dem Ergebnis eine vollständige SGR-Sequenz (\33[...m).

Gebräuchliche Bestandteile der Sequenz sind:

1 für fett,
4 für unterstrichen,
5 für blinken,
7 für inverse Darstellung,
39 für Standard-Vordergrundfarbe,
30 bis 37 für die Farben im Vordergrund,
90 bis 97 für Vordergrundfarben im 16-Farben-Modus,
38, 5, 0 bis 38,
5, 255 für Vordergrundfarben in den 88-Farben- und 256-Farben-Modi,
49 für die Standard-Hintergrundfarbe,
40 bis 47 für Hintergrundfarben,
100 bis 107 für Hintergrundfarben im 16-Farben-Modus und
48, 5, 0 bis 48,
5, 255 für Hintergrundfarben in den 88-Farben- und 256-Farben-Modi.

LC_ALL, LC_COLLATE, LANG
Diese Variablen legen die Locale für die Kategorie LC_CTYPE fest. Sie bestimmt die Sortierreihenfolge, mit der Ausdrücke zur Angabe eines Bereichs wie beispielsweise [a-z] ausgewertet werden.

LC_ALL, LC_CTYPE, LANG
Diese Variablen legen die Locale für die Kategorie LC_CTYPE fest. Diese bestimmt den Zeichentyp eines jeden Zeichens, beispielsweise welche Zeichen als Leerraum angesehen werden.

LC_ALL, LC_MESSAGES, LANG
Diese Variablen wählen die Locale für die Kategorie LC_MESSAGES. Diese legt fest, in welcher Sprache grep seine Meldungen ausgibt. Die Standard-Locale C verwendet Meldungen in amerikanischem Englisch.

POSIXLY_CORRECT
Falls gesetzt, verhält sich grep strikt nach dem POSIX.2-Standard. Anderenfalls ähnelt sein Verhalten eher dem anderer GNU-Programme. POSIX.2 verlangt von Optionen, die nach einem Dateinamen angegeben sind, dass sie als Dateinamen behandelt werden. Normalerweise behandelt grep sie immer als Optionen, gleichgültig an welcher Stelle sie auftreten. Ferner verlangt POSIX.2, unbekannte Optionen als »unzulässig« anzuzeigen. In den Standardeinstellungen meldet grep sie lediglich als »ungültig«. POSIXLY_CORRECT deaktiviert auch _N_GNU_nonoption_argv_flags_, das im Folgenden genauer beschrieben wird.

_N_GNU_nonoption_argv_flags_
(Hier ist N die numerische Kennung des grep-Prozesses.) Falls das i-te Zeichen dieser Umgebungsvariablen den Wert 1 hat, wird das i-te Argument von grep nicht als Option verarbeitet, selbst wenn es wie eine Option aussieht.

Ein Befehlszeileninterpreter kann diese Umgebungsvariable für jeden von ihm ausgeführten Befehl setzen, um anzuzeigen, welche der Argumente durch Ersetzung von Platzhaltern Mustererkennung von Dateinamen erzeugt worden sind und deshalb keinesfalls als Optionen berücksichtigt werden sollen. Dieses Verhalten steht nur in Verbindung mit der GNU-C-Bibliothek zur Verfügung und nur dann, wenn POSIXLY_CORRECT nicht gesetzt ist.



Rückgabewert


Der Rückgabewert ist 0, wenn die gewählten Zeilen gefunden werden, sonst 1. Wenn ein Fehler auftrat, ist der Rückgabewert 2.



PCRE RegExp Patterns


Einführung in reguläre Ausdrücke


RegExp resp. Regex (regular expressions bzw. reguläre Ausdrücke) sind von primärer Signifikanz; das (Textanalyse-)Tool (Textanalyse-Werkzeug) grep steht also namentlich für ...

... global / regular expression /print bzw.
global search for a regular expression and print out matched lines!

Das Durchsuchen von beliebigen (Text-)Dateien nach dem gewünschtem 'PATTERN' (MUSTER), also z.B. dem (regulären) Ausdruck ist demnach seine Disziplin!

Durch Verwendung sog. regulärer Ausdrücke wird man befähigt alle möglichen Arten von Text (Daten) hinzuzufügen, zu löschen od. auszugeben; also kurzum, besagte Daten demenstprechend zu bearbeiten bzw. verarbeiten.

Geschickt formulierte 'Ausdrücke' können ihre diesbzgl. Arbeit(-sabläufe) signifikant vereinfachen. Zudem setzen div. Kommandos (z. B. sed, awk, ...) aus der Unix- / Linux-Welt ebenso wie viele Programmiersprachen auf (besagte) reguläre Ausdrücke!

Reguläre Ausdrücke differenzieren in ihren möglichen Varianten; so bieten Java u. Perl jeweils Ihre eigene Syntax für die Bildung betreffender Ausdrücke. Anwendungen wie Sendmail u. Oracle haben zudem ihre eigene Version regulärer Ausdrücke.

(GNU) grep verwendet jedoch die GNU-Version regulärer Ausdrücke; diese ähnelt der POSIX-Syntax stark - ist allerdings nicht vollkommen identisch mit dieser! Fakt ist hierbei immerhin, dass die meisten Varianten regulärer Ausdrücke syntaktisch sehr ähnlich sind, dennoch gibt es diesbetreffend alles entscheidene Unterschiede. Folglich verhalten sich sowohl Escape-Zeichen, Metazeichen als auch spezielle Operatoren in Abhängigkeit von der Art des regulären Ausdruckes, (welchen Sie verwenden) entsprechend unterschiedlich.

Die Verwendung des selben (regulären) Ausdruckes kann also (jeweils) zu komplett anderen Resulaten führen, soweit Sie besagten Ausdruck (wie vorstehend erwähnt) unter verschiedenen 'Varianten' (regulärer Ausdrücke) benutzen sollten.

Wir werden hier allerdings lediglich jene reguläre Ausdrücke behandeln (erläutern) welche von grep und grep im Perl-Stil (grep -P) verwendet werden. Für gewöhnlich werden reguläre Ausdrücke beim Kommando grep im nachstehendem Format verwendet:


grep [options] [regexp] [filename]



Reguläre Ausdrücke setzen sich aus zwei Arten von Zeichen zusammen:
Gewöhnliche Textzeichen, also sog. Literalen bzw. Sonderzeichen wie dem Asterisk (*), letztere nennt man auch Metazeichen. Eine Escape-Folge ermöglicht eine Verwendung von Metazeichen als Literal sowie die Kennzeichnung besonderer Zeichen od. Bedingungen (Wortgrenzen / "Tab-Zeichen").

Die Zeichenkette (in englisch als String bezeichnet), welche es zu finden gilt, ist also der Zielstring. Der reguläre Ausdruck wiederum das gesamte Suchmuster, das eingegeben werden muss, um betreffenden Zielstring dann auch finden zu können. Das Suchmuster kann selbstverständlich auch literal 1:1 mit dem Zielstring identisch sein bzw ggf. auch einige der regulären 'Ausdrucksfunktionen' beinhalten, welche dann aber gleichbleibend behandelt werden.



Anführungszeichen bei regulären Ausdrücken


Üblicherweise, wird der reguläre Ausdruck (od. RegExp) in einfachen Anführungszeichen notiert (also dem (Anführungszeichen-)Symbol auf der Tastatur über der Rautetaste [#], nicht jenes Sonderzeichen neben der Taste mit dem ß).

Hierfür gibt es natürlich ein paar ziemlich gute Gründe. Einer der Gründe ist, das Unix-Shells das Leerzeichen i. d. R. als das Ende / Beginn eines Arguments werten.

Im zuvor gezeigtem Format wird also der reguläre Ausdruck durch ein Leerzeichen vom Dateinamen getrennt. Doch wie sollte verfahren werden wenn die Zeichenkette, nach der Sie suchen möchten, ein Leerzeichen enthält?

Inbesondere hinsichtlich vorbenannter Fragestellung sollten Sie grep (und anderen Unix-Kommandos) durch Anführungszeichen (syntaktisch richtig) mitteilen, an welcher Stelle ein Argument beginnt bzw. endet.

Ein weiterer Grund ist, dass verschiedene Arten von Anführungszeichen sehr unterschiedliche Auswirkungen auf Shell-Kommandos wie grep haben. So verursacht eine Benutzung des Backticks (das ist jenes Anführungszeichen, welches durch Drücken der Taste rechts neben dem ß und der Umschalttaste erzeugt wird), dass die Konsole (Shell) alles innerhalb (obig erwähneter) Anführungszeichen als Kommando (Befehl) interpretiert und demzufolge auch ausführt, das Ergebnis expandiert dann in eine Zeichenkette und wird dann (z. B.) wie untenstehend verwendet:


grep `whoami` filename



Somit würde also beispielsweise das Kommando whoami ausgeführt werden (dieses gäbe sodann den Benutzernamen zurück, unter welcher die Shell auf Unix-Systemen läuft) und sein Ergebnis würde wiederum als Suchstring verwendet werden.

Wenn Sie sich also mit dem Benutzernamen "grepmaster" anmelden, so würde grep die Datei filename nach der Verwendung von "grepmaster" durchforsten.

Doppelte Anführungszeichen hingegen funktionieren ebenso wie einfache Anführungszeichen, der alles entscheidende Unterschied dabei ist allerdings dass in doppelten Anführungszeichen notierte Suchmuster Umgebungsvariablen zu Ihrem (beinhaltendem) Wert (Inhalt) expandieren lassen; einfache Anführungsstriche dagegen ermöglichen dies nicht:


grep "$HOME" filename



Die Umgebungsvariable HOME beinhaltet (wie üblich) den absoluten Pfad des Home-Verzeichnisses (des gerade angemeldeten) Benutzers. Das eben gezeigte grep-Kommando würde demnach den Wert (Inhalt) der (Umgebungs-)Variablen HOME ermitteln und als dessen Folge nach exakt dieser Zeichenkette suchen.

Wenn man nun $HOME in einfachen Anführungszeichen notieren würde, könnte die Umgebungsvariable logischerweise mitnichten zu Ihrem Inhalt (Wert) expandieren.

Daher ist es überaus wichtig, reguläre Ausdrücke mit den jeweils geeigneten Anführungszeichen zu versehen.

Anfangs- und Endanführungszeichen müssen also identischen Typs sein (dürfen sich somit nicht unterscheiden), andernfalls würde ein (syntaktischer) Fehler produziert werden.

Allerdings gilt es hierbei zu beachten, dass es dennoch möglich ist, verschiedene Anführungszeichen miteinander zu kombinieren, um eine bestimmte Funktionalität zu erlangen.



Metazeichen


Nicht nur die Anführungszeichen selbst sondern auch die Position und Kombination etwaiger Sonderzeichen sorgt für unterschiedlichste Effekte in regulären Ausdrücken.

Beispielspielsweise sucht das nachfolgende Kommando in der Datei name.list nach dem Literal (Buchstaben) 'e', gefolgt von einem 'a':


grep -e 'e[a]' name.list



Jedoch würde durch dass Anfügen eines Zirkumflex ^, vorstehender Ausdrucks signifikant anders interpretiert werden. Nun würden Sie nach Auswertung des veränderten Ausdrucks einem 'e', gefolgt von irgendetwas, was aber nicht der Buchstabe 'a' ist suchen:


grep -e 'e[^a]' name.list



Metazeichen haben somit ziemlich starke Auswirkungen, genau deshalb ist es ganz besonders wichtig, mit ihrer Verwendung ausreichend vertraut zu sein. Eine Liste der regelmäßig verwendeten Sonderzeichen und ihrer Bedeutungen entnehmen Sie bitte nachfolgender Tabelle.


Metazeichen (Zeichen mit Sonderbedeutung)NamePasst zu
Elemente, die zu einem einzelnen Zeichen passen
.PunktJedes Zeichen
[...]ZeichenklasseJedes beliebige Zeichen in den eckigen Klammern
[^...]Negierte ZeichenklasseJedes beliebige Zeichen, das nicht in den eckigen Klammern aufgeführt ist
\charEscape-ZeichenDas literale Zeichen nach dem Slash; wird verwendet, wenn Sie nach einem Sonderzeichen suchen wollen, wie zum Beispiel nach "$" (dann verwenden Sie "\$") Elemente, die zu einer Position passen
^ZirkumflexAnfang einer Zeile
$DollarzeichenEnde einer Zeile
\<Backslash, kleiner alsAnfang eines Wortes
\>Backslash, größer alsEnde eines Wortes
Quantifikatoren
?FragezeichenOptionales Match
*AsteriskJede Anzahl (auch Null); manchmal als allgemeine Wildcard genutzt
+PluszeichenMindestens ein Vorkommen des vorigen Ausdrucks
{N}Finde genauFinde genau N Vorkommen
{N,}Finde mindestensFinde mindestens N Vorkommen
{min,max}Angegebener BereichFinde zwischen min und max Vorkommen
Andere
|AlternationFinde einen der beiden Ausdrücke
-StrichSteht für einen Bereich
(...)Runde KlammernBegrenzen des Gültigkeitsbereichs einer Alternation
\1, \2, ...RückverweisPasst zu Text, der vorher innerhalb von Klammern passte (zum Beispiel erstes Set, zweites Set usw.)
\bWortgrenzeFasst Zeichen zusammen, die normalerweise ein Wort beenden (z. B. Leerzeichen, Punkt usw.)
\BBackslashAlternative zur Verwendung von "\\", um einen Backslash zu finden, Verwendung für bessere Lesbarkeit
\wWortzeichenWird verwendet, um ein beliebiges "Wort"-Zeichen zu finden (ein Buchstabe, eine Ziffer und der Unterstrich)
\WNichtwort zeichenDamit werden alle Zeichen gefunden, die nicht in Wörtern verwendet werden (also keine Buchstaben, Ziffern oder der Unterstrich)
\`Start eines PuffersPasst zum Start eines Puffers, der an grep geschickt wurde
\'Ende eines PuffersPasst zum Ende eines Puffers, der an grep geschickt wurde



Es gibt sicherlich Fall-Konstellationen, in welchen Sie (z. B.) nach einem literalen Zeichen suchen möchten, welches üblicherweise als Metazeichen benutzt wird.

Nehmen wir einmal an Sie suchen innerhalb der Datei price.list nach einer Zeichenkette welche aus Zahlen besteht, dieser (Zeichenkette) aber am Ende ein Dollarzeichen angefügt ist, so würde der folgende Ausdruck leider nicht den eigentlich gewünschten String finden:


grep '[1-9]$' price.list



Denn als Resultat wird die Suche versuchen, die Zahlen am Ende einer jeden Zeile zu finden; dass war jedoch bestimmt nicht dass was Ihnen hierbei vorschwebte.

Sofern das Escape-Zeichen als Literal erkannt werden soll und somit auch seine eigentliche Sonderbedeutung verlieren soll, so müssten Sie folgerichtig bei der Nutzung besagter Escape-Zeichen darauf achten diesen einen Backslash (\) voranzustellen:


grep '[1-9]\$' price.list



Hier wird (wie eben gerade erklärt) das Metazeichen $ als Literal behandelt und daher in price.list als String (Zeichenkette) gesucht.

Wenn z. B. die Textdatei (price.list) den folgenden Inhalt hat ...:


123
123$



... so würde die Verwendung der eben gezeigten Kommandos nachstehendes Resultat zu Tage fördern:


$ grep '[1-9]\$' price.list
123$

$ grep '[1-9]$' price.list
123



Dem ersten Beispiel enstprechend, sucht das Kommando nach dem eigentlichen Dollarzeichen als Literal. Das zweite Beispiel wertet das Dollarzeichen hingegen nicht als Literal sondern als Metazeichen mit seiner Sonderbedeutung, und passt somit auf das Ende einer Zeile.

Das hat dann also zur Folge dass nur Zeilen gefunden werden, welche mit einer Ziffer enden.

Hier eine knappe Zusammenfassung der Metazeichen für reguläre Ausdrücke (inkl. einiger Beispiele, welche die Benutzung der Regex etwas veranschaulichen sollen):


. (Jedes beliebige Zeichen)
Der "Punkt" als Wildcard (Jokerzeichen), wird ziemlich oft in regulären Ausdrücken verwendet; dieses Zeichen (der Punkt) '.' passt nämlich zu jedem x-beliebigen Zeichen. Das ist gerade dann besonders vorteilhaft, wenn ein Nutzer ein Suchmuster verwenden möchte, bei welchem sich ein Zeichen mittendrin befindet, welches der Benutzer leider nicht kennt.

So würde demgemäß das nachstehende grep-Muster zu "red", "rod", "red", "rzd" etc. passen:


'r.d'



Der Punkt darf natürlich auch mehrfach verwendet werden, um dementsprechend mehrere unbekannte Zeichen (auch hintereinander) abzubilden.


[...] (Zeichenklasse)
Das "Zeichenklassen"-Tool ist übrigens eines der flexibleren Werkzeuge und wird daher bei regulären Ausdrücken immer wieder gerne angewendet. Im Übrigen gibt es zwei grundlegende Optionen (Möglichkeiten) um eine Zeichenklasse zu verwenden um (entweder) einen Bereich oder eine Liste mit Zeichen festzulegen.

Man sollte dabei allerdings ganz besonders beachten, dass eine Zeichenklasse immer nur zu einem Zeichen passen kann:


'[a-f]'
'[aeiou]'



Das erste Muster sucht hier nach einem x-beliebigen Buchstaben zwischen "a" und "f".

Bereiche können Groß- bzw. Kleinbuchstaben od. Ziffern beinhalten. Eine Kombination von Bereichen darf ebenfalls genutzt werden, z. B. [a-fA-F0-5]. Im zweiten Beispiel wird nach einem der dortig angegebenen Zeichen gesucht - hier also demzufolge nach Vokalen.

Eine Zeichenklasse darf auch eine Liste mit Sonderzeichen beinhalten, leider lassen sich diese nicht als Bereich verwenden.


[^...] (Negation)
Die "Negations"-Zeichenklasse ermöglicht es seinem Nutzer, nach allem zu suchen außer einem ganz bestimmten Zeichen resp. Zeichenklasse.

Wenn also ein Benutzer beispielswiese keine geraden Zahlen mögen sollte, so könnte er das untenstehende Suchmuster benutzen:


'..[^24680]'



Somit würde dann nach einem beliebigen 3-stelligen Muster gesucht werden, welches nicht mit einer geraden Ziffer endet. Eine negierte (also sozusagen in's Gegenteil verkehrte) Zeichenklasse kann eine beliebige Liste bzw. Bereich mit Zeichen beinhalten.


\ (Escape)
Das "Escape"-Zeichen ist eines derjenigen Metazeichen (Zeichen mit Sonderbedeutung), welches in Abhängigkeit von seiner Benutzung eine differenzierte (unterschiedliche) Entsprechung (Bedeutung) haben kann.

Steht es also vor einem anderen Metazeichen, wird dieses dadurch als literales Symbol und somit nicht mehr als ein Zeichen mit besonderer Bedeutung erkannt bzw. gewertet.

(Es kann auch zusammen mit anderen Zeichen, wie beispielsweise b bzw. ' verwendet werden, um dadurch eine besondere Bedeutung zu erlangen.)

Werfen Sie einen Blick auf die folgenden zwei Beispiele:


'.'
'\.'



Beispiel Nummer Eins, würde auf jedes einzelne Zeichen passen und deshalb den kompletten Text einer Datei ausgeben. Das zweite Beispiel hingegen, würde jedoch lediglich auf das eigentliche "Punkt"-Zeichen passen.

Mit dem Escape-Zeichen wird dem regulären Ausdruck mitgeteilt, das die besondere Bedeutung eines Metazeichens schlichtweg ignoriert werden soll (das Zeichen wird sodann als Literales-Symbol interpretiert resp. verarbeitet.


^ (Zeilenanfang)
Wenn ein Zirkumflex (ein sog. Caret) außerhalb einer Zeichenklasse benutzt wird, negiert es die Zeichenklasse nicht (kehrt die Bedeutung der Zeichenklasse also nicht um); nein, in diesem Falle steht es lediglich für den Anfang einer jeden Zeile.

Nutzt man das Caret (Zirkumflex) einzeln, passt es zu jeder Zeile auf dem Bildschirm aus dem ganz einfachen Grund weil natürlich jede Zeile auch einen Zeilenanfang besitzt (logisch). Nützlicher ist das Caret, wenn ein Nutzer Zeilen finden möchte, die mit einem ganz bestimmten Muster beginnen (die Betonung liegt hier auf BEGINNEN):


'^red'



Vorstehendes Muster würde auf alle Zeilen passen, welche mit "red" beginnen, aber nicht auf jene, die nur irgendwo in der Zeile das Wort "red" beinhalten. Praktisch ist das z. B. bei der strukturierten Kommunikation von Programmiersprachen, bei denen die Zeilen mit speziellen Strings (Zeichenketten) anfangen.


$ (Zeilenende)
Wie zuvor bereits erwähnt passt das Dollarzeichen auf das Ende einer jeden Zeile. Für sich allein genutzt, würde jede Zeile in einem Stream - außer die letzte - gefunden werden, weil diese mit einem "Dateiende"-Zeichen anstatt mit einem "Zeilenende"-Zeichen abschließt. Praktisch ist dass immer dann wenn man Zeichenketten finden möchte, welche am Ende einer Zeile eine bestimmte Bedeutung haben, wie in dem folgenden Beispiel:


'-$'



Damit würden jetzt aber auch wirklich alle Zeilen gefunden werden, deren letztes Zeichen einem Bindestrich entspricht. Ganz allgemein trifft das auf Wörter zu, welche (mittels Bundestrich) getrennt werden, sofern sie nicht mehr in eine Zeile passen. Dieser Ausdruck würde daher nur jene Zeilen finden, welche am Ende ein (durch Bindestrich) getrenntes Wort haben.


\< (Wortanfang)
Wenn ein Benutzer also ein Suchmuster formulieren möchte, das am Anfang eines Wortes gefunden werden soll, dieses sich aber auch im Wort selbst wiederholen kann, so lässt sich diese Escape-Folge dafür nutzen. Riskieren Sie einfach einen Blick auf das nachfolgende Beispiel:


'\<un'



Dieses Muster hier passt auf Wörter mit der ersten Silbe (denn bei "unter-" ist nicht das "un-" das Präfix, sondern das ganze Wort "unter-") "un", wie z. B. "unvorstellbar", "unentdeckt" od. "unterbewertet". Es passt allerdings mitnichten auf Wörter wie beispielsweise "fundiert", "Flunder" od. "rund".

Das Muster findet also einen Wortanfang, indem es lediglich nach einem Leerzeichen bzw. einem anderweitigen Trennzeichen sucht, das für ein neues Wort steht (Punkt, Komma etc.).


\> (Wortende)
Analog zur eben vorgestellten Escape-Folge passt diese hier nun auf das Ende eines Wortes. Nach den Zeichen schaut es nach einem Trennzeichen, das für das Ende eines Wortes steht (Leerzeichen, Tab, Punkt, Komma etc.), wie hier unten veranschaulicht:


'ing\>'



Dieses Muster passt auf Wörter, welche auf "ing" enden (z. B. "spring"), nicht aber auf Wörter, welche "ing" bloß beinhalten (z. B. "bringen").


* (allgemeiner Joker)
Das Asterisk ist warscheinlich die am weitaus häufigsten genutze Wildcard. Das Stern-Symbol ist ein allgemeiner Joker, der als Quantifikator klassifiziert ist und vorallem für sich wiederholende Muster benutzt wird.

Bei manchen Metazeichen können Sie Unter- und Obergrenzen festlegen, mit welcher sich jene vom Muster ausgegebene Anzahl an Wiederholungen entsprechend limitieren lässt; das Asterisk-Symbol (Stern-Symbol) kennt allerdings keine Grenzen (es ist also gierig (greedy)).

Es ist überdies auch völlig egal, wie viele Leerzeichen es vor oder nach dem Zeichen nun gibt. Stellen Sie sich einfach vor, ein Benutzer möchte jetzt bloß herausfinden, ob die div. Formate eines Installers in einer Datei beschrieben sind oder nicht. Man könnte dafür jetzt also dieses überaus simple Kommando nutzen:


'install.*file'



Das Resultat sollte somit alle Zeilen ausgeben, welche "install" und "file" (aneinander gehangen) beinhalten - natürlich mit (beliebig vielen) anderen Zeichen dazwischen. Es ist deshalb also unbedingt notwendig, den Punkt (als Metazeichen) zu verwenden, denn sonst würde lediglich "installfile" gefunden werden, nicht aber die div. Iterationen von "install" und "file" mit anderen Zeichen dazwischen.


- (Bereich)
Sofern man den Bindestrich innerhalb einer in eckigen Klammern stehenden Zeichenklasse verwendet, legt dieser einen Bereich von Werten fest, anstatt bloß eine simple Liste mit direkt angegebenen Zeichen zu benutzen. Ist der Bindestrich jedoch außerhalb einer solchen Klasse notiert (angegeben), wird selbiger (der Bindesstrich) als literaler Bindestrich genutzt und hat demnach keine besondere Bedeutung mehr (wird als nicht als Metazeichen interpretiert).


'[0-5]'



\# (Rückverweise)
Rückverweise (Backreferences) ermöglichen es Ihnen überdies, sich auf jene zuvor gefundenen Muster entsprechend zu beziehen (also darauf einfach bloß zu verweisen), um eben zukünftige Muster zu finden. Einen Rückverweis notieren Sie durch (einen Backslash) \, gefolgt von einer Musterposition in der Sequenz (von links nach rechts), auf welche verwiesen wird.


\b (Wortgrenze)
Die Escape-Folge \b bezieht sich auf jedes Zeichen, welches angibt, dass ein Wort begonnen bzw. beendet wurde (also ganz ähnlich wie die oben behandelten Folgen \> und \<). In diesem Kontext (Zusammenhang) ist es aber wirklich egal, ob es sich nun um den Anfang od. das Ende des Wortes handelt - es wird lediglich nach simplen Satzzeichen bzw. Leerzeichen gesucht.

Das ist immer dann vorteilhaft, wenn Sie nach einer Zeichenkette suchen, die sowohl als eigenständiges Wort existieren kann, als auch innerhalb eines anderen davon unabhängigen Wortes vorkommen kann:


'\bheart\b'



Obiges Beispiel würde daher ausschließlich und exakt auf das Wort "heart" passen, mitnichten aber auf andere Strings (also nicht "disheartening", od. "hearts" etc.). Sollten Sie nach einem ganz bestimmten Wort, einem numerischen Wert resp. einer Zeichenkette suchen und möchten aber nicht, dass diese Wörter bzw. Werte Teil eines anderen Werts sind, so sollten Sie lieber \b, \> od. \< benutzen.


\B (Backslash)
Was jetzt aber die Escape-Folge \B betrifft, so ist diese ein echter Sonderfall, es handelt sich dabei nicht um eine eigene Escape-Folge, sondern nur um einen Alias für eine andere Folge. Hier ist daher \B also absolut identisch mit \\, diese Vorgehensweise stellt damit lediglich eine weitere Möglichkeit dar das Backslash-Zeichen in einem Suchmuster literal und somit ohne seine spezielle Bedeutung (folglich nicht als Metazeichen) benutzen zu können.

Der Sinn und Zweck dieses Aliases besteht demnach darin, das Suchmuster ein wenig besser lesbar zu machen und damit doppelte Backslashes zu vermeiden, (welche in komplexen Ausdrücken manigfaltige Bedeutungen haben können).


'c:\Bwindows'



Folgendes Beispiel würde nach der Zeichenkette "c:\windows" suchen.


\w und \W (Wort- und Nichtwortzeichen)
Zu den beiden nachfolgenden Escape-Folgen \w und \W könnte man nun sagen, dass diese gewissermaßen zusammen gehören weil ihre Entsprechungen (Bedeutungen) genau entgegengesetzt sind. \w passt auf jedes "Wort"-Zeichen und entspricht somit (etwas anders ausgedrückt) bloß ''[a-zA-Z0-9_]''.

Die Escape-Folge \W passt auf jedes andere Zeichen (einschließl. der nicht druckbaren Zeichen), welche auch nicht in die Kategorie "Wortzeichen" passen. Beim Parsen strukturierter Dateien kann dass ganz praktisch (vorteilhaft) sein, wenn Text durch Sonderzeichen (z. B. :, $, % usw.) unterbrochen ist.


\` (Anfang des Puffers)
Vorstehende Escape-Folge passt ganz ähnlich wie jene Escape-Folge "Zeilenanfang" zum Anfang eines jeden Puffers, welcher an das Kommando übergeben wird und welcher den regulären Ausdruck verarbeitet. Weil grep nunmal bekanntlich mit Zeilen arbeitet, sind ein Puffer und eine Zeile sozusagen synonym (aber nicht immer). Diese Escape-Folge wird also genauso wie die Escape-Folge "Zeilenanfang" verwendet, welche etwas weiter oben erläutert wurde.


\' (Ende des Puffers)
Diese Escape-Folge ist der Escape-Folge "Zeilenende" ziemlich ähnlich, nur passt sie dabei zum Ende eines Puffers, der an das den regulären Ausdruck verarbeitende Programm übergeben wird. Die Escape-Folgen für den Anfang und das Ende eines Puffers werden - im Übrigen - wirklich sehr selten genutzt und es ist sowieso sehr viel einfacher, anstatt dessen einfach nur nach Zeilenanfang und Zeilenende zu suchen.

Diese nachstehenden Metazeichen werden in erweiterten regulären Ausdrücken benutzt:


? (optionales Match)
Das Fragezeichen hat in regulären Ausdrücken eine ganz andere Bedeutung als bei seiner sonstigen Verwendung als Wildcard in Dateinamen (GLOB). Bei GLOB stellt ein ? ein beliebiges Zeichen dar. In regulären Ausdrücken bedeutet es hingegen, dass das vorige Zeichen (bzw. die vorige Zeichenkette, wenn diese sich in einem Untermuster befindet) ein "optionales" Muster ist. So ist es dann auch möglich mehrere Suchbedingungen in einem einzelnen regulären Muster abzubilden; beispielsweise wie hier unten:


'colors?'



Hier würde also "color" aber natürlich auch "colors" passen. Das Zeichen "s" ist somit bloß optional - ist es also nicht vorhanden, passt das Muster logischerweise dennoch.


+ (wiederholtes Match)
Mit dem Pluszeichen wird übrigens festgelegt dass der reguläre Ausdruck nach einem einmaligen resp. mehrfachen Match des vorigen Zeichens (od. Untermusters) sucht, wie hier nachstehend gezeigt:

'150+'



Demnach würde 150 mit einer x-beliebigen Anzahl angefügter Nullen passen (also beispielsweise 1500, 15000, 1500000 etc.).


{N} (genau N Mal passend)
Geschweifte Klammern nach einem Zeichen legen die exakte Anzahl von Wiederholungen fest, nach welchen gesucht werden soll, wie untenstehend auch veranschaulicht wurde:


'150{3}\b'



Dies passt jetzt ganz genau auf "15", gefolgt von exakt drei Nullen. Aus diesem Grunde würde "1500" selbstverständlich nicht passen, aber wie gesagt "15000". Beachten Sie die Benutzung der Escape-Folge \b als eine Wortgrenze. Würde diese hier nicht genutzt, kämen letztlich nicht lediglich "15000", sondern gar "150000", "150002345" od. auch "15000asdf" infrage, dass hängt damit zusammen dass diese alle den gewünschten Suchstring "15000" beinhalten.


{N,} (mindestens N Mal passend)
Ebenso wie im obigen Beispiel wird hier eine Zahl nur diesmal zusätzlich noch ein Komma genutzt, so dass der reguläre Ausdruck deshalb nach mindestens N Vorkommen sucht, z. B. wie hier dargestellt:


'150{3,}\b'



Obiges Beispiel passt damit auf "15", gefolgt von mind. drei Nullen, aus diesem Grunde würden "15", "150" und "1500" logischerweise nicht passen können. Es ist daher ziemlich sinnvoll die Escape-Folge für die Wortgrenze zu nutzen, wenn Sie genau eine bestimmte Zahl haben möchten (also z. B. einen Output wie "1500003456", "15000asdf" etc. vermeiden möchten).


{N,M} (zwischen N und M Mal passend)
Soweit Sie für die Wiederholungen einen Minimal- und einen Maximalwert notieren möchten, können sie diese (beiden) Werte in geschweifte Klammern schreiben, natürlich separiert (getrennt) durch ein Komma, wie hier unten gezeigt:


'150{2,3}\b'



Somit würde dass auf "1500" ebenso wie auf "15000" passen, andere Strings würde der Ausdruck jedoch nicht finden.


| (Alternation)
Das "Pipe"-Zeichen legt Alternationen innerhalb eines regulären Ausdrucks fest. Nehmen wir einfach mal an, Sie möchten dem regulären Ausdruck damit eine bunte Auswahl von zu erfüllenden Bedingungen für einen einzelnen Ausdruck geben, wie hier nachstehend veranschaulicht:


'apple|orange|banana|peach'



Damit würde eine beliebige der angegebenen Zeichenketten passen, ganz egal ob sich die anderen Zeichenketten (Strings) nun auch im Suchumfeld befinden. Im vorstehendem Fall passt der Inhalt also auch dann, wenn der Text wahlweise nur "apple" od. "orange" od. "banana" od. auch "peach" beinhaltet.


( ) (Untermuster)
Die letzte wichtige Eigenschaft der erweiterten regulären Ausdrücke ist die Option, entsprechende Untermuster zu formulieren (erstellen). So können reguläre Ausdrücke ganze Zeichenketten wiederholen, Alternationen für ganze Zeichenketten benutzen, Rückverweise nutzen und ganz allgemein besser lesbar werden:


'(red|blue) plate'
'(150){3}'



Das erste Beispiel passt hier also entweder auf "red plate" od. aber auf "blue plate". Ohne die jeweiligen Klammern würde der reguläre Ausdruck ''red|blue plate'' zu "red" (beachten Sie das Fehlen des Wortes "plate") od.
"blue plate" passen.

Untermuster in Klammern helfen Ihnen dabei, den Gültigkeitsbereich einer Alternation zu limitieren. Im zweiten Beispiel passt der reguläre Ausdruck auf "150150150".

Ohne die entsprechenden Klammern würde hingegen "15000" gefunden werden. Klammern ermöglichen Ihnen, die Wiederholung einer ganzen Zeichenkette zu suchen, und nicht bloß ein einzelnes Zeichen.

Die Metazeichen sind ganz allgemein für die div. grep-Kommandos nutzbar, z. B. egrep, fgrep und grep -P. Es gibt aber auch Instanzen, in welchen ein Zeichen eine ganz andere Entsprechung besitzt.



POSIX-Zeichenklassen


RegExp beinhalten zusätzlich eine ganze Menge von POSIX-Zeichendefinitionen, welche Abkürzungen für bestimmte Klassen von Zeichen bereitstellen. Nachstehende Tabelle zeigt eine solche Liste dieser Abkürzungen und ihrer jeweiligen Entsprechungen.

POSIX ist prinzipiell ein Standard, welcher vom Institute of Electrical and Electronics Engineers (IEEE) konzipiert worden ist, um zu (normen bzw.) empfehlen, wie sich unixartige Betriebssysteme verhalten sollten. Er ist ziemlich alt, wird aber dennoch bis dato im Großen und Ganzen benutzt. Unter anderem legen POSIX Definitionen fest, wie genau die regulären Ausdrücke mit Shell-Werkzeugen wie grep genutzt werden sollten.

Hier die Tabelle der POSIX-Zeichendefinitionen.


POSIX-DefinitionZeichendefinition
[:alpha:]Jeder Buchstabe, unabhängig von Groß- und Kleinschreibung
[:digit:]Jedes Ziffernzeichen
[:alnum:]Jeder Buchstabe oder jedes Ziffernzeichen
[:blank:]Leerzeichen oder Tabzeichen
[:xdigit:]Hexadezimale Zeichen; jede Ziffer od. A-F od. a-f
[:punct:]Jedes Satzzeichen
[:print:]Jedes ausdruckbare Zeichen (aber keine Kontrollzeichen)
[:space:]Jedes Zeichen für Whitespace
[:graph:]Alles außer Whitespace-Zeichen
[:upper:]Alle Großbuchstaben
[:lower:]Alle Kleinbuchstaben
[:cntrl:]Kontrollzeichen



Die meisten POSIX-Definitionen sind lediglich besser lesbare Äquivalente von Zeichenklassen. So könnte z. B. [:upper:] auch als [A-Z] notiert werden, dies wäre sogar die kürzere Schreibweise. Für einige andere Klassen wie [:cntrl:] existieren aber leider keine besser lesbaren Äquivalente von Zeichenklassen.

Um diese Klassen wiederum in regulären Ausdrücken abzubilden, benutzen Sie sie genau wie eine Zeichenklasse.

Es ist daher äußerst wichtig, sich bewusst zu machen, dass eine derartige Nutzung besagter POSIX-Zeichendefinitionen bloß auf ein einzelnes Zeichen passt. Um Wiederholungen dieser Zeichenklassen zu ermöglichen, müssen Sie die betreffenden Definition entsprechend wiederholen, z. B. wie hier nachfolgend gezeigt:


'[:digit:]'
'[:digit:][:digit:][:digit:]'
'[:digit:]{3}'



Das erste Beispiel findet lediglich ein einsames numerisches Zeichen. Das zweite Beispiel wird lediglich 3-stellige (od. größere) Zahlen finden. Im dritten Beispiel wird eine schönere, übersichtlichere, da kürzere Möglichkeit gezeigt, die gleiche Funktionalität aus dem zweiten Beispiel zu erlangen.

Es ist also keine schlechte Idee reguläre Ausdrücke nach Möglichkeit in kurzen Mustern abzubilden und dennoch mind. die selbe Funktionalität zu erreichen. Das dritte Beispiel ist - meines Erachtens nach - der effizientere Weg, um genau das Gleiche wie im zweiten Beispiel zu erreichen.



Aufbau eines regulären Ausdrucks


Genau wie auch in der Mathematik, gibt es ebenso bei grep gewisse Regeln für die Prioritäten bei einer Verarbeitung. Wiederholungen erfolgen vor dem Verketten.

Verkettung wird wiederum vor Alternationen ausgeführt. Zeichenketten werden verkettet, indem man sie einfach (ganz plump) nebeneinander im regulären Ausdruck notiert - es gibt keine spezielle Vorgehensweise, um so eine Verkettung vorzunehmen. Werfen Sie mal einen Blick auf das untenstehende Beispiel resp. den folgenden regulären Ausdruck:


'pat{2}ern|red'



In besagtem Beispiel wird die Wiederholung also zuerst umgesetzt, was zu zwei "t"s führt. Danach werden die Zeichenketten miteinander verkettet, was zu "pattern" auf der einen Seite des Pipe-Zeichens und "red" auf der anderen Seite des Pipe-Zeichens führt.

Nun wird die Alternation verarbeitet, damit auch ein regulärer Ausdruck entstehen kann, welcher hier nach "pattern" od. "red" sucht. Aber wie sollten Sie nun verfahren, wenn Sie nach "patpatern" und "red" od. "pattern" od. "pattred" suchen möchten?

Ganz einfach - in diesem Fall werden simple Klammern genutzt, um betreffende Prioritätsregeln einfach zu "überschreiben", genau wie hier unten näher erläutert wird:


2 + 3 / 5
(2 + 3) / 5



Aufgrund der Nutzung von Klammern kommt es im obigen Beispiel zu unterschiedlichen Resultaten. Das Konzept ist hier untenstehend allerdings genau das gleiche:


'(pat){2}ern|red'
'pat{2}(ern|red)'



Im ersten Muster wird "pat" erstmal verkettet, erst dann wird es zweimal wiederholt, was sodann zu "patpatern" und "red" als Such-Zeichenkette führt. Im zweiten Beispiel wird erst das Alternationsuntermuster verarbeitet, somit wird der reguläre Ausdruck nach "pattern" und "pattred" suchen.

Die Nutzung von Klammern kann für Sie insofern von Vorteil sein, dass Sie hierdurch den regulären Ausdruck optimieren können; so werden dann bestimmte Inhalte abhängig davon gefunden werden, wie Sie den Ausdruck formuliert haben. Auch wenn die Prioritätsregeln für einen bestimmten regulären Ausdruck nicht überschrieben werden müssen, ist es dennoch manchmal sinnvoll, Klammern zu nutzen, um die Lesbarkeit (damit) deutlich zu erhöhen.

Ein regulärer Ausdruck kann (wie unten ersichtlich) (über mehrere Zeilen) fortgesetzt werden, solange das sich öffnende einfache Anführungszeichen nicht (am Ende des Ausdrucks) geschlossen wird; wie hier erklärt:


$ grep'patt
> ern' filename



Hier ist das schließende einfache Anführungszeichen noch nicht notiert worden, obschon der Benutzer schon die Eingabetaste gedrückt hatte - also direkt nach dem zweiten "t" (ohne ein weiteres Leerzeichen).

In der nächsten Zeile wird demzufolge ein solcher Prompt ">" gezeigt, welcher damit angibt, dass die Shell immer noch auf das Schließen der Zeichenkette wartet; es wird also erst mit der Verarbeitung des Kommandos fortgefahren wenn das schließende Anführungszeichen notiert und Enter gedrückt wurde.

Solange Sie also weiterhin "nur" die Eingabetaste drücken sollten, wird unermüdlich dieser Prompt (Eingabeaufforderung) von der Kommandozeile ausgegeben werden, bis Sie entweder Strg-C drücken, um das Kommando abzubrechen, od. (wie vorstehend erwähnt) das schließende Anführungszeichen eintippen, damit das Kommando ausgeführt werden kann.

So lassen sich übrigens überlange reguläre Ausdrücke auf der Kommandozeile (bzw. in ein Shell-Skript) schreiben, ohne dass Sie den ganzen Input in eine einzige Zeile quetschen müssten und den Code somit weniger gut lesbar machen zu würden.

Wie eben beschrieben sucht der reguläre Ausdruck das Wort "pattern". Das Kommando ignoriert wie zuvor erläutert Zeilenumbrüche und fügt diese auch nicht in den Ausdruck selbst ein, so ist es möglich, mitten im Wort einfach Enter zu drücken und in der nächsten Zeile weiterzuschreiben.

Man muss sich hierbei dennoch ein wenig Gedanken um die Lesbarkeit machen, weil "Leerzeichen" für gewöhnlich nicht so leicht erkennbar sind. Natürlich können Sie auch mehrere verschiedene Zeichenketten jeweils in ihren eigenen Anführungszeichen gruppieren, z. B. so:


'patt''ern'



Wie obig notiert würde hier also nach dem Wort "pattern" gesucht werden, und zwar genau so als hätten Sie beispielsweise einfach ''pattern'' eingetippt. Dieses Beispiel ist natürlich nicht wirklich praktisch, und es gibt daher normalerweise auch keinen guten Grund, den Text derart zu notieren.

Da die Umgebungsvariable $HOME - üblicherweise - auf das Home-Verzeichnis des (aktuell angemeldeten) Nutzers zeigt (z. B. /home/grepmaster) und das Kommando whoami wiederum immer den Namen des (derzeit angemeldeten) Benutzers (z. B. "grepmaster") ausgibt, könnte man vor diesem Hintergrund nachfolgenden Ausdruck formulieren ...:


'username:'`whoami`' and home directory is '"$HOME"



... um sodann (wie hier, beispielsweise) die Zeichenkette "username:grepmaster and home directory is /home/grepmaster" zu finden.

So kann also das Kommando whoami und der Wert (Inhalt) der (Umgebungs-)Variablen $HOME geschickt genutzt werden. Dies hier ist aber lediglich ein kleiner Überblick über reguläre Ausdrücke und ihre gekonnte Anwendung. Es gibt zahlreiche Bücher, welche sich mit der gesamten Komplexität regulärer Ausdrücke ausgiebig befassen; wir beschränken uns hier jedoch weitestgehend auf dass was Sie für die sinnvolle Verwendung des Kommandos grep benötigen.



Einfache reguläre Ausdrücke (grep resp. grep -G)


Dieser Abschnitt legt sein Augenmerk besonders auf das Basis-grep. Die meisten der Basis-grep-Optionen sind aber auch für alle anderen Versionen von grep gültig (nutzbar). Basis-grep bzw. grep -G ist der Standardmustererkennungstyp, welcher beim Aufruf von grep benutzt wird.

grep wertet die angegebenen Muster als einfache reguläre Ausdrücke, wenn es das Kommando ausführt. Dies ist das Standard-grep-Programm, deshalb ist die Option-G eigentlich immer redundant.

Wie jedes Kommando hat auch grep eine ganze Reihe von Optionen, welche festlegen, welche Übereinstimmungen gefunden werden und wie grep die Resultate ausgibt. Die GNU-Version von grep unterstützt die meisten der in den nachgelagerten Unterabschnitten vorgestellten Optionen.



Optionen zur Übereinstimmung


-e pattern, --regexp=pattern
grep -e -style doc.txt



Hier wird sichergestellt, dass grep jenes Muster als regulären Ausdruck interpretiert. Das ist immer dann sehr hilfreich, soweit der reguläre Ausdruck mit einem Bindestrich anfängt, dadurch sieht dieser wie eine Option aus. In diesem Beispiel schaut grep nach Zeilen, welche auf "-style" passen.

-f file, --file=file
grep -f pattern.txt searchhere.txt



Holt sich die Muster aus file. Diese Option befähigt Sie, alle Muster, welche Sie auf eine Übereinstimmung prüfen möchten, in einer Datei zu speichern; diese trägt hier den Namen pattern.txt. Jetzt schaut grep erstmal nach ob jene Muster aus pattern.txt in der betreffenden Datei searchhere.txt überhaupt vorkommen.

Die Muster ergänzen sich einander, grep gibt also jede Zeile zurück, welche auf eines der Muster passt. Die Musterdatei muss ein Muster per Zeile aufweisen. Wenn pattern.txt also leer ist, wird folglich auch nichts gefunden werden können.


-i, --ignore-case
grep -i 'help' me.txt



Ignoriert Groß- resp. Kleinschreibung im angegebenen regulären Ausdruck, ganz egal ob dieser nun auf der Kommandozeile eingegeben wird od. aber mittels der Option -f auf eine Datei verwiesen wird in welcher besagter Ausdruck eingetragen ist.

Im angegeben Beispiel würde in der Datei me.txt nach der Zeichenkette "help" gesucht werden, hierbei würde Groß- und Kleinschreibung entsprechend berücksichtigt werden (es würden also z. B. "HELP", "HelP" etc. gefunden werden). Ein ähnliches, jedoch obsoletes Synonym für besagte Option ist -y.


-v, --invert-match
grep -v oranges filename



Gibt hier jene Zeilen zurück, welche nicht passen. In obigen Beispiel würde daher jedwede Zeile aus filename ausgegeben werden, die eben nicht das Muster "oranges" enthält.


-w, --word-regexp
grep -w 'xyz' filename



Passt nur, wenn betreffender Eingabetext aus kompletten Wörtern besteht. Bei vorstehenden Beispiel reicht es nicht aus, dass eine Zeile die drei Buchstaben "xyz" hintereinander beinhaltet, es müssen sich zusätzlich Leerzeichen bzw. Satzzeichen um diese herum befinden.

Buchstaben, Ziffern und der Unterstrich werden als Teil eines Wortes angesehen - alle anderen Zeichen gelten nur als Wortgrenze, ebenso wie der Anfang und das Ende der Zeile. Das entspricht damit der Nutzung von \b am Anfang und Ende des regulären Ausdrucks.


-x, --line-regexp
grep -x 'Hello, world!' filename



Wie -w, nur hier muss dann auch die komplette Zeile passen. In diesem Beispiel werden alle Zeilen gefunden, deren gesamter Inhalt aus "Hello, world!" besteht. Zeilen mit zusätzlichem Inhalt werden daher nicht gefunden.

Das kann beim Parsen von Logdateien überaus hilfreich sein, gerade dann wenn Sie nach bestimmten Inhalten suchen, welche auch noch in anderen Zusammenhängen vorhanden sind.



Optionen für die Ausgabe


-c, --count
grep -c contact.html access.log



Statt dem regulärem Output erhalten Sie lediglich die Anzahl der gefundenen Übereinstimmungen. In diesem Beispiel wird grep also lediglich exakt angeben wie oft die Datei contact.html in einem Zugriffslog eines Webservers auftaucht.


grep -c -v contact.html access.log



Im vorstehenden Beispiel wird nun aber nicht mehr die Anzahl der Übereinstimmung auf contact.html ausgegeben, nein - hier wird nachgesehen wie viele Zeilen eben nicht auf diesen String passen.

In betreffendem Fall würde somit von grep mitgeteilt werden, wie oft jemand nun auf betreffende Datei des Webservers zugegriffen hat, bei welcher es sich aber eben nicht um die Zeichenkette contact.html handelt; die Suche wird also invertiert (sozusagen ins Gegenteil verkehrt). Alle Zeilen die somit nicht auf contact.html passen stellen demnach eine Übereinstimmung dar (also quasi eine Negation des Suchstrings)


--color[=WHEN], --colour[=WHEN]
grep -color[=auto] regexp filename



Soweit die Konsole das anzeigen von Farben unterstützt, hebt grep betreffende Muster in dem Output farblich hervor. Die Farbe wird mittels Umgebungsvariable GREP_COLORS definiert.
WHEN hat drei Optionen: never, always und auto.


-l, --files-with-matches
grep -l "ERROR:" *.log



Statt des normalen Outputs werden hier lediglich jene Namen der Eingabedateien ausgegeben, welche auch das betreffende Muster beinhalten. Wie bei -L stoppt die Suche also schon direkt beim ersten Treffer.

Wenn ein Administrator also bloß an jenen Dateinamen interessiert ist, welche ein Muster beinhalten und nicht alle Zeilen welche passen sehen möchte, dann ist diese Option goldrichtig.

So kann grep auch beschleunigt werden, weil besagte Suche in betreffender Datei in dem Moment abgebrochen wird, in dem das Muster gefunden worden ist. Sonst würde grep allerdings bis zum Ende der Datei weitersuchen. Diese Vorgehensweise bezeichnet man auch als "lazy matching".


-L, --files-without-match
grep -L 'ERROR:' *.log



Anstatt des normalen Outputs werden also lediglich jene Namen der Eingabedateien ausgegeben, welche eben keine passenden Inhalte haben. So gibt dieses Beispiel also all jene Logdateien aus, welche keine Fehlermeldungen beinhalten.

Dies ist eine überaus effiziente Nutzung von grep, weil grep somit lediglich exakt so lange sucht bis eine entsprechende Übereinstimmung (ein Treffer) gefunden worden ist. Das heißt also das nicht immer die komplette Datei durchforstet werden muss.


-m NUM, --max-count=NUM
grep -m 10 'ERROR:' *.log



Diese Option hier macht grep klar, lediglich so viele Zeilen zu durchforsten (in diesem Falle sind es 10 Zeilen) welche den String "ERROR:" beinhalten. Das ist beim Lesen sehr großer Dateien wirklich sehr vorteilhaft, gerade dann wenn Wiederholungen ziemlich wahrscheinlich sind, wie es beispielsweise bei Logdateien der absolute Regelfall ist. Wenn Sie also lediglich schauen möchten, ob entsprechende Zeichenketten auch vorhanden sind, ohne dabei die Konsole vollzumüllen, dann sind Sie sehr gut damit beraten wenn Sie diese Option benutzen.


-o, --only-matching
grep -o pattern filename



Gibt lediglich den passenden Text aus, nicht aber die gesamte Eingabezeile. Das ist immer dann von großem Vorteil, wenn Sie grep dazu nutzen möchten, um beispielsweise eine Festplattenpartition od. eine Binärdatei auf bestimmte Muster hin zu prüfen.

So würde lediglich jenes Muster ausgegeben werden, welches gefunden wurde, ohne dabei irgendwelche zusätzlichen Inhalte mit zu übermitteln (welche auch in der Zeile stehen und), welche für die Konsole problematisch werden könnten (Binärmüll etc.).


-q, --quiet, --silent
grep -q pattern filename



Unterdrückt den Output. Das Kommando liefert aber dennoch aufschlußreiche Informationen, weil der Exit-Status von grep entsprechend geprüft werden kann (0 für Erfolg, also wenn das Muster gefunden wurde, 1, wenn es nicht gefunden wurde, und 2, wenn sich das Programm wegen eines Fehlers nicht ausführen ließ).

Diese Option nutzt man in Skripten, um das Vorkommen eines Musters in einer Datei zu überprüfen dabei allerdings keinen unnötigen Output erzeugen möchte.


-s, --no-messages
grep -s pattern filename



Unterdrückt alle Fehlermeldungen, welche durch nicht existente Dateien bzw. Berechtigungsprobleme entstehen. Das ist bei solchen Skripten von Vorteil, welche das gesamte Dateisystem ohne root-Berechtigungen durchsuchen sollen und aus nachvollziebarem Grunde mit großer Wahrscheinlichkeit Berechtigungsfehler ausgeben würden, welche logischerweise in diesem Kontext nicht von weiter von Belang sind. Zum anderen werden leider auch interessante resp. diagnostische Informationen unterdrückt; hierdurch werden Probleme ggf. nicht erkannt.



Optionen für die Gestaltung des Outputs


-b, --byte-offset
grep -b pattern filename



Einfache reguläre Ausdrücke (grep od. grep -G) Zeigt den Byte-Offset von jedem gefundenen Text anstatt der Zeilennummer an. Das erste Byte in der Datei ist natürlich 0, und nicht sichtbare Zeilenendzeichen (Newline in Unix) werden auch mitgezählt.

Da per Standard immer nur ganze Zeilen ausgegeben werden, ist jene angezeigte Zahl selbstverständlich der Byte-Offset des Zeilenanfangs. Das ist ganz besonders bei der Analyse von Binärdateien, dem Bauen von Patches und anderen Aufgaben hilfreich, bei welchen Zeilennummern nicht weiter von Belang sind.


grep -b -o pattern filename



Die Optionen -b -o geben den Offset inkl. dem gefundenen Muster aus.

-H, --with-filename
grep -H pattern filename



Gibt den Dateinamen gefolgt von der gefundenen Zeichenkette aus. Dieses Verhalten ist nicht nur Standard - soweit Sie mehr als eine Datei durchsuchen - es ist obendrein auch ganz praktisch, wenn Sie bloß eine Datei durchsuchen und den Dateinamen im Output haben möchten. Bedenken Sie dabei aber, dass hier relative (und nicht absolute) Pfade resp. Dateinamen verwendet werden.


-h, --no-filename
grep -h pattern *



Hier ist das Gegenstück zu -H. Wenn Sie mehr als bloß eine einzige Datei bearbeiten, wird der Output des Dateinamens vor jeder gefundenen Zeile unterdrückt. Dies ist wiederum ein Standardverhalten, sofern lediglich eine Datei od. die Standardeingabe involviert sind, und ganz praktisch obendrein, jedenfalls dann wenn es (z. B.) darum geht auch hier wieder Dateinamen zu unterdrücken, da ganze Verzeichnisse durchsucht werden sollen.


--label=LABEL
gzip -cd file.gz | grep --label=LABEL pattern



Wenn die Daten über die Standardeingabe reinkommen (z. B., weil der Output einer anderen Datei an grep weitergeleitet wird), versieht die Option --label die Zeile mit LABEL. Bei diesem Beispiel gibt das Kommando gzip den Inhalt der unkomprimierten Datei file.gz aus und gibt den Output als Input an grep weiter.


-n, --line-number
grep -n pattern filename



Wie obig dargestellt, wird die Zeilennummer jeder angezeigten Zeile gefolgt von der gefundenen Zeichenkette ausgegeben; dabei ist die erste Zeile der Datei die 1 (also keine nullbasierte Zählung). Dies kann beim Debuggen von Code ganz hilfreich sein, denn so können Sie anschließend die Datei in einem Editor öffnen und zielgerichtet zur gewünschten Zeile springen.


-T, --initial-tab
grep -T pattern filename



Fügt vor jeder gefundenen Zeile ein sog. Tab-Zeichen ein, so dass es zwischen jenen von grep erzeugten Informationen und dem eigentlichen Zeileninhalt steht. Diese Option ist praktisch, um das Layout übersichtlicher zu gestalten. So lassen sich beispielsweise Zeilennummern, Byte-Offsets, Labels etc. vom gefundenen Text separieren.


-u, --unix-byte-offsets
grep -u -b pattern filename



Diese Option hier funktioniert lediglich auf MS-DOS- und Microsoft Windows-Plattformen und muss im Übrigen mit -b aufgerufen werden. Sie berechnet den Byte-Offset so, als würde das Programm auf einem Unix-System laufen und entfernt zudem die Carriage-Return-Zeichen.


-Z, --null
grep -Z pattern filename



Gibt nach jedem Dateinamen ein ASCII NUL aus (das ist ein Byte mit dem Wert 0). Das ist immer dann besonders praktisch wenn man Dateinamen verarbeitet, welche Sonderzeichen beinhalten (wie beispielsweise Carriage Returns).



Anpassen des Kontextes


-A NUM, --after-context=NUM
grep -A 3 Copyright filename



Macht den Kontext gefundener Zeilen dadurch sichtbar, dass jeder Übereinstimmung NUM nachfolgende Zeilen (mit) ausgegeben werden. Zwischen den Gruppen von Übereinstimmungen wird ein Gruppentrenner (--) eingefügt. Bei diesem Beispiel werden nach jeder passenden Zeile die folgenden drei Zeilen mit ausgegeben.

Das ist immer dann sehr vorteilhaft, wenn Sie einen Quellcode durchsuchen möchten. Das Beispiel gibt nach jedem gefundenen "Copyright" die drei hierauf folgenden Zeilen mit aus.


-B NUM, --before-context=NUM
grep -B 3 Copyright filename



Hier das gleiche Konzept wie bei der Option -A NUM, bloß dass betreffende Zeilen vor der Übereinstimmung ausgegeben werden und nicht die danach. Das ist natürlich ebenfalls beim Durchsuchen von Quellcode sehr praktisch. Im angegebenen Beispiel werden jene drei Zeilen vor jeder Zeile ausgegeben, welche die Zeichenkette "Copyright" enthalten (dieser String steht recht häufig in Quellcodedateien ganz oben).


-C NUM, -NUM, --context=NUM
grep -C 3 Copyright filename



Die Option -C NUM verhält sich so, als wenn der Benutzer beide Optionen, also -A NUM und -B NUM eingetippt hätte. Es werden NUM Zeilen vor und nach der Übereinstimmung ausgegeben.

Zwischen den Gruppen von Übereinstimmungen wird überdies ein Gruppentrenner (--) eingefügt. Bei diesem Beispiel werden jeweils drei Zeilen vor und nach der passenden Zeile ausgegeben. Das ist ziemlich praktisch wenn man Quellcode durchsuchen möchte.



Auswahl von Dateien und Verzeichnissen


-a, --text
grep -a pattern filename



Entspricht der Option --binary-files=text, mit welcher Binärdateien so verarbeitet werden können, als wenn es sich hierbei um Textdateien handeln würde.


--binary-files=TYPE
grep --binary-files=TYPE pattern filename



TYPE kann einen der folgenden Werte haben: binary, without-match od. text.


Wenn grep also eine Datei das erste Mal untersucht, bestimmt es, ob die Datei eine "Binärdatei" ist (also eine Datei ist welche aus für Menschen nicht lesbaren Inhalten besteht), und passt seinen Output entsprechend an. Per Standard wird bei einer Übereinstimmung in einer Binärdatei lediglich die Information "Binary file somefile.bin matches" ausgegeben. Das Standardverhalten kann selbstverständlich auch mit der Option --binary-files=binary festgelegt werden.

Hat TYPE aber den Wert without-match, durchforstet grep die Binärdatei nicht und verhält sich einfach so, als wenn es keine Übereinstimmung gäbe (entspricht auch der Option -l). Wenn TYPE den Wert text hat, wird die Binärdatei wie Text behandelt (entspricht der Option -a).

Es kann vorkommen das --binary-files=text Binärmüll ausgibt, welcher von der Shell dann teilweise als Kommando verstanden werden kann. Dadurch gerät die Konsole durcheinander und ist solange nicht mehr nutzbar, bis Sie zurückgesetzt wird. Das lässt sich mit den Kommandos tput init und tput reset ganz gut bewerkstelligen.


-D ACTION, --devices=ACTION
grep -D read 123-45-6789 /dev/hda1



Ist die Eingabedatei aber eine spezielle Datei, wie beispielsweise ein FIFO bzw. ein Socket, so teilt diese Option grep entsprechend mit, wie es sich hier verhalten soll. Per Standard verarbeitet grep jene Dateien so, als wenn es sich um ganz gewöhnliche Dateien im System handeln würde. Ist also ACTION auf skip gesetzt, wird grep sie schlichtweg ignorieren.

Wenn der Wert read ist, wird grep das Device so lesen, als wenn es sich um eine reguläre Datei handelt. Im Beispiel wird eine ganze Festplattenpartition nach der angezeigten falschen Sozialversicherungsnummer durchsucht.


-d ACTION, --directories=ACTION
grep -d ACTION pattern path



Diese Option sagt grep, wie Verzeichnisse zu behandeln sind, welche grep als Eingabedateien übergeben werden. Hat ACTION den Wert read, wird das Verzeichnis so gelesen, als wenn es sich um eine Datei handelt. recurse durchforstet die Dateien innerhalb des Verzeichnisses (das kommt der Option -R gleich), und skip überspringt das Verzeichnis, ohne es dieses zu durchsuchen.


--exclude=GLOB
grep --exclude=PATTERN path



Passt die Liste der Eingabedateien an, indem grep angewiesen wird, jene Dateien zu ignorieren, welche dem angegebenen Muster entsprechen. PATTERN kann ein kompletter Dateiname sein od. die typischen "GLOB"-Joker beinhalten, welche die Konsole beim suchen von Dateien nutzt (*, ? und []). So werden beispielsweise mittels --exclude=*.exe alle Dateien übersprungen, welche auf .exe enden.


--exclude-from=FILE
grep --exclude-from=FILE path



Vorstehende Option kommt der Option --exclude gleich, nur dass eine Liste mit Mustern aus einer angegebenen Datei geholt wird, in welcher jedes Muster in einer Zeile steht. grep wird dann all jene Dateien ignorieren, die auf exakt die Zeilen passen, welche in besagter Liste mit betreffenden Mustern stehen.


--exclude-dir=DIR
grep --exclude-dir=DIR pattern path



Alle Verzeichnisse im Pfad, welche auf das Muster DIR passen, werden aus den rekursiven Suchen ausgeschlossen. Hier muss das zu ignorierende Verzeichnis (relativ od. absolut) angegeben werden, damit es entsprechend ausgeschlossen werden kann. Um diese Option sinnvoll zu nutzen, sollte man selbige gemeinsam mit den Optionen -r bzw. -d recurse verwenden.


-l
grep -l pattern filename



Kommt der Option --binary-files=without-match gleich. Hat grep eine Binärdatei gefunden, tut es einfach so, als ob es keine Übereinstimmung in der Datei gibt.


--include=GLOB
grep --include=*.log pattern filename



Beschränkt die Suche auf Eingabedateien, deren Namen dem angegebenen Muster entsprechen (hier also auf Dateien, die auf .log enden). Diese Operation ist gerade dann besonders praktisch soweit Sie beabsichtigen Verzeichnisse mittels der Option -R zu durchsuchen.

Dateien, welche dem angegebenen Muster nicht entsprechen, werden also schlichtweg ignoriert. Es können somit entweder ein kompletter Dateiname angegeben od. die üblichen "GLOB"-Wildcards eingesetzt werden, welche auch die Konsole zum Finden von Dateien verwendet (*, ? und []).


-R, -r, --recursive
grep -R pattern path
grep -r pattern path



Durchsucht alle Dateien in allen Verzeichnissen, welche als Eingabedateien an grep übergeben werden.



Weitere Optionen


--line-buffered
grep --line-buffered pattern filename



Verwendet Zeilenpuffer für den Output. So ein Output führt im Allgemeinen zu einer schnelleren Verarbeitung. Das Standardverhalten von grep ist, eine ungepufferte Ausgabe zu nutzen. Die Verwendung dieser Option ist meist reine Geschmackssache.


--mmap
grep --mmap pattern filename



Nutzt die Funktion mmap() anstatt read(), um Daten zu verarbeiten. Das kann einen Performancegewinn bedeuten, aber leider auch zu Fehlern führen, soweit es I/O-Probleme gibt bzw. die Datei kleiner wird, während man sie durchforstet.


-U, --binary
grep -U pattern filename



Eine Option, die spezifisch für MS-DOS/Windows ist und grep explizit anweist, alle Dateien als Binärdateien zu betrachten. Normalerweise würde grep Carriage Returns entfernen, bevor es anfängt, zu suchen, diese Option jedoch, überschreibt das Verhalten.

Dadurch müssen Sie aber leider beim Schreiben von Mustern expliziter vorgehen. Wenn beispielsweise Inhalte in einer Datei dem Muster entsprechen, aber leider einen Zeilenumbruch beinhalten, ist eine solche Suche nach diesem Muster nicht von Erfolg gekrönt.


-V, --version


Gibt lediglich die Versionsinformationen von grep aus und beendet sodann das Programm.


-z, --null-data
grep -z pattern



Eingabezeilen werden so behandelt, als wenn alle mit einem Null-Byte (od. dem Zeichen ASCII NUL) enden anstatt mit einem Zeilenumbruch. Diese Option ist den Optionen -Z bzw. --null ganz ähnlich, bloß dass es hier um die Eingabe geht, nicht aber um die Ausgabe.

Eine abschließende Einschränkung zum Basis-grep:
Die Metazeichen der "erweiterten" regulären Ausdrücke -, ?, +, {, }, |, -- funktionieren nicht mit Basis-grep. Jene durch diese Zeichen bereitgestellten Funktionen sind dann nutzbar, wenn Sie diese durch ein führendes Escape-Zeichen ergänzen.



Erweiterte reguläre Ausdrücke (egrep bzw. grep -E)


grep -E und egrep sind funktional identisch (es ist das selbe Kommando). Sie durchsuchen Dateien nach Mustern, welche als erweiterte reguläre Ausdrücke betrachtet werden. Ein erweiterter regulärer Ausdruck benutzt nicht nur die schon erwähnten Optionen, er verwendet darüber hinaus Metazeichen, um kompliziertere und mächtigere Suchstrings zu erstellen.

Die benutzten Kommandozeilenoptionen sind bei grep -E und grep vollkommen gleich - der einzige Unterschied ist der, wie diese das Suchmuster verarbeiten:


?
Das Fragezeichen (?) in einem Ausdruck macht etwas optional. Jedes Zeichen, welches vor dem Fragezeichen steht, kann im Zielstring auftauchen, muss es jedoch nicht. Stellen Sie sich beispielsweise vor, Sie würden nach dem Wort "behavior" suchen, welches aber auch als "behaviour" notiert werden könnte. Anstatt die Oder-Option (|) zu benutzen, könnten Sie folgendes Kommando verwenden:


egrep 'behaviou?r' filename



Im Resultat ist jene Suche ebenso für "behavior" wie auch für "behaviour" erfolgreich, weil diese die An- und Abwesenheit des Buchstabens "u" erlaubt.


+
Das Pluszeichen greift das vorige Zeichen auf und lässt unendlich viele Wiederholungen bei der Suche nach passenden Zeichenketten zu. Das folgende Kommando würde sowohl "pattern1" als auch "pattern11111" finden, nicht aber "pattern":


egrep 'pattern1+' filename



{n,m}
Die geschweiften Klammern werden verwendet, um zu bestimmen, wie oft sich ein Muster wiederholt, bevor es passt. Statt also nach "patternnnn" zu schauen, könnten Sie auch das untenstehende Kommando anwenden:


egrep 'pattern{4}' filename



So wird jede Zeichenkette gefunden, welche "patternnnn" beinhaltet, ohne dass man hierbei den sich wiederholenden Teil entsprechend häufig eingeben muss. Um mindestens vier Wiederholungen zu bekommen, können Sie das nachstehende Kommando benutzen:


egrep 'pattern{4,}' filename



Werfen Sie einen Blick auf das nächste Beispiel:


egrep 'pattern{,4}' filename



Auch wenn es zu den verwendeten Konventionen passt, ist dies dennoch kein gültiger Ausdruck.
Das gezeigte Kommando würde nicht zu entsprechenden Resultaten führen, weil es einfach nicht möglich ist,
"nicht mehr als X Übereinstimmungen" zu erhalten. Um zwischen vier und sechs Wiederholungen zu finden, nutzen Sie dies:


grep 'pattern{4,6}' filename



|
Wird in einem regulären Ausdruck genutzt, um ein "Oder" zu ermöglichen. So erlaubt die Pipe (|) es Ihnen, div. Muster mit einem Ausdruck zu kombinieren. Stellen Sie sich beispielsweise vor, dass Sie einen von zwei Namen in einer Datei suchen müssen. Das bewerkstelligen Sie mit nachstehendem Kommando:


egrep 'name1|name2' filename



Es würden dann Zeilen gefunden, welche entweder "name1" od. "name2" beinhalten.


( )
Klammern können verwendet werden, um bestimmte Textstrings für Rückverweise, Alternationen zu "gruppieren" (sorgt auch für bessere Lesbarkeit). Außerdem kann die Nutzung von Klammern dabei behilflich sein, Mehrdeutigkeiten so aufzulösen, wie es der Benutzer sich wünscht. Muster innerhalb von Klammern werden meist als Untermuster (Subpatterns) bezeichnet.

Klammern begrenzen auch den Gültigkeitsbereich von Pipes (|). Damit kann der Anwender exakter bestimmen, welche Zeichenketten Teil der "Oder"-Operation sind. Um beispielsweise nach Zeilen zu suchen, welche entweder "pattern" od. "pattarn" beinhalten, könnten Sie das untenstehende Kommando nutzen:


egrep 'patt(a|e)rn' filename



Ohne jene Klammern würde das Suchmuster patta|ern heißen, was wiederum zu den Zeichenketten "patta" bzw. "ern" passt - ein ganz anderes Resultat als das, was eigentlich gewünscht war.

In den einfachen regulären Ausdrücken negiert der Backslash (\) das Verhalten eines Metazeichens und bewirkt, dass das Zeichen als literal angesehen wird. Das passiert in egrep ebenfalls, hier aber gibt es eine signifikante Ausnahme. Das Metazeichen { wird vom klassischen egrep leider nicht unterstützt.

Auch wenn einige Versionen \{ literal interpretieren, so sollte es dennoch in egrep -Mustern vermieden werden. Stattdessen sollte man lieber auf [{] ausweichen, um betreffendes Zeichen zu finden, ohne dabei die besondere Bedeutung auszulösen.

Es ist nicht ganz korrekt, dass das Basis-grep diese Metazeichen nicht benutzt. Sie lassen sich zwar nutzen, nur leider nicht direkt. Jedoch muss jedem der Metazeichen aus den erweiterten regulären Ausdrücken ein Escape-Zeichen vorangestellt werden, sodass seine besondere Bedeutung ausgelöst wird.

Bedenken Sie aber, dass das die umgekehrte Form des normalen Verhaltens ist, bei welchem ein Escape-Zeichen die besondere Bedeutung entfernt.


Einfache reguläre Ausdrücke Erweiterte reguläre Ausdrücke
'\(red\)''(red)'
'a\{1,3\}''a{1,3}'
'behaviou\?r''behaviou?r'
'pattern\+''pattern+'



Durch vorstehende Tabelle können Sie sicherlich nachvollziehen, weshalb die meisten Leute die prinzipielle Benutzung des erweiterten grep bevorzugen, wenn sie erweiterte reguläre Ausdrücke verwenden. Ein idealer regulärer Ausdruck sollte explizit sein und so wenige Zeichen wie möglich verwenden.





Feste Zeichenketten (fgrep od. grep -F)


Hier behandeln wir grep -F resp. fgrep. fgrep steht für Fixed String resp. Fast grep. "Fast Grep" dehalb weil es vergleichsweise schneller ist als grep und egrep. Das ist möglich, indem es reguläre Ausdrücke erst gar nicht benutzt und nur nach festen Stringmustern schaut. Praktisch ist dass, wenn man z. B. nach statischen Inhalten sucht. Um fgrep aufzurufen, tippt man dies hier ein:


fgrep string_pattern filename



fgrep ist konzipiert worden um schnell und unkompliziert bedient zu werden und rasch Ergebnisse zu liefern; aus diesem Grunde sind div. Kommandozeilenoptionen reduziert. Die bekannteste ist:


-b.
fgrep -b string_pattern filename



Zeigt jene Blocknummer an, an welcher das string_pattern gefunden wurde. Per Standard werden immer ganze Zeilen ausgegeben, es handelt sich logischerweise bei der Byte-Nummer um den Byte-Offset des Zeilenanfangs.


-c
fgrep -c string_pattern filename



So wird die Anzahl jener Zeilen gezählt, welche eine od. mehrere Instanzen von string_pattern beinhalten.


-e, -string
fgrep -e string_pattern filename



Wird benutzt, um mehr als bloß ein Muster zu suchen, od. wenn das string_pattern mit einem Bindestrich anfängt. Obschon Sie auch einfach nur eine neue Zeile nutzen könnten, um mehr als eine Zeichenkette zu notieren, könnten Sie auch stattdessen die Option -e mehrfach verwenden; dass ist beim schreiben von Skripten ganz praktisch:


fgrep -e string_pattern1

-e string_pattern2 filename
-f file

fgrep -f newfile string_pattern filename



Packt die Resultate Ihrer Suche in eine neue Datei, anstatt diese auf der Shell auszugeben. Dies ist ein anderes Verhalten als jenes bei der Option -f in grep - denn dort wird auf diese Art und Weise eine Datei die entsprechende Suchmuster enthält spezifiziert.


-h
fgrep -h string_pattern filename



Sofern Sie in mehr als bloß einer Datei suchen sollten, bewirkt -h, dass fgrep die Dateinamen vor den gefundenen Resultaten ausgibt.


-i
fgrep -i string_pattern filename



Mit der Option -i wird fgrep angewiesen, Groß- und Kleinschreibung in string_pattern bei der Suche zu ignorieren.


-l
fgrep -l string_pattern filename



Gibt all jene Dateien aus, welche string_pattern beinhalten, jedoch nicht die eigentlich gefundenen Zeilen.


-n
fgrep -n string_pattern filename



Gibt eine entsprechende Zeilennummer vor jeder gefundenen Zeile aus.


-v
fgrep -v string_pattern filename



Findet all jene Zeilen, welche nicht string_pattern enthalten.


-x
fgrep -x string_pattern filename



Gibt alle Zeilen aus, bei denen string_pattern auf die komplette Zeile passt. Das ist übrigens wiederum ein Standardverhalten von fgrep und muss somit nicht explizit angegeben werden.



Reguläre Ausdrücke im Perl-Stil (grep -P)


Reguläre Ausdrücke im Perl-Stil verwenden die Perl-Compatible Regular Expressions-(PCRE-)Bibliothek, um die Muster zu interpretieren und diesbzgl. Suchen entsprechend durchzuführen. Wie der Name schon schon ganz richtig vermuten lässt, wird hier also die Perl-Implementierung regulärer Ausdrücke genutzt.

Perl hat nämlich den großen Vorteil, dass es für das Suchen resp. Bearbeiten von Texten hervorragend optimiert worden ist. PCRE ist also sehr viel effizienter und bietet demnach auch mehr Funktionen. Die Konsequenz ist leider aber auch, dass es ziemlich schwierig und kompliziert werden kann.

Denn um mittels PCRE an die gewünschten Informationen zu kommen, ist (anders ausgedrückt so) als würde ein Gehirnchirurg versuchen mit einer Kettensäge eine Gehirnoperation durchzuführen: Eine solche Aufgabe lässt sich (auf diese Weise) zwar mit minimalem Aufwand lösen, aber es verursacht natürlich eine ziemliche Sauerei.

Die besonderen Suchmöglichkeiten bzw. -optionen welche PCRE bereit hält, hängen aber nicht von grep selbst ab, vielmehr greifen sie auf die libpcre-Bibliothek und die zugrunde liegende Perl-Version zurück. Das heißt, dass es ziemlich große Unterschiede zwischen verschiedenen Rechnern bzw. Betriebssystemen geben kann.

Für gewöhnlich halten die Manpages "pcrepattern" resp. "pcre" betreffende rechnerspezifischen Informationen zu den Optionen bereit. Nachfolgelnd erhalten Sie einen kurzen Überblick über jene PCRE-Suchfunktionen, welche auf den meisten Rechnern verfügbar sein sollten.

Bedenken Sie aber auch, dass die regulären Ausdrücke im Perl-Stil nicht zwangsläufig per Standard auf Ihrem Betriebssystem vorhanden sein müssen. Fedora- bzw. Red Hat-basierte Systeme beinhalten diese meistens (sofern natürlich die entsprechende PCRE-Bibliothek installiert ist). Debian beispielsweise, hält allerdings keine regulären Ausdrücke im Perl-Stil in seinem diesbzgl. grep-Paket bereit.

Alternativ gibt es jedoch ein Programm namens pcregrep, welches eine dem Aufruf von grep -P ähnelnde Funktionalität anbietet. Es steht selbstverständlich jedem frei, sein ganz persönliches grep-Binary zu kompilieren, welches dann auch PCRE-Unterstützung beinhaltet. Um nun zu checken, ob Ihre grep-Version auch reguläre Ausdrücke im Perl- Stil unterstützt od. eben nicht, bedienen Sie sich z. B. einfach des nachstehenden Kommandos:


$ grep -P test /bin/ls
grep: The -P option is not supported



Das bedeutet ganz Allgemein, das beim Bauen von grep die Bibliothek libpcre nicht gefunden werden konnte bzw. dass diese bewusst beim Kompilieren mittels der Option --disable-perl-regexp weggelassen worden ist.

Jetzt kann mann entweder die libpcre einfach nachinstallieren und grep sodann neu kompilieren od. lediglich ein passendes Paket für das eigene Betriebssystem ausfindig machen. Die übliche Form bei der Nutzung von grep im Perl-Stil sieht - im Übrigen - so aus:


grep -P options pattern file



Ganz anders als bei grep -F und grep -E gibt es jedoch kein Kommando "pgrep". Das Kommando pgrep wird nämlich benutzt, um nach aktiven Prozessen auf einem Computer zu suchen.

Alle Kommandozeilenoptionen für grep funktionieren also auch bei grep -P, lediglich die Muster werden hier anders abgearbeitet. PCRE stellt zusätzliche Metazeichen und Zeichenklassen bereit, welche für eine erweiterte Suchfunktionalität verwendet werden können.

Mal abgesehen von den ergänzenden Metazeichen und Klassen wird ein Muster ganz genauso aufgebaut wie es bei einem klassischen regulären Ausdruck der Regelfall ist. Hier behandeln wir jetzt lediglich vier Aspekte der PCRE-Optionen:
Zeichentypen, Suchen nach oktalen Zeichen, Zeicheneigenschaften und PCRE-Optionen.



Zeichentypen


Auch wenn es hier eine gewisse Überlappung mit dem normalen grep gibt, bringt PCRE glücklicherweise seine hauseigenen Escape-Zeichen mit, welche sich beim Suchen erfreulicherweise etwas robuster verhalten. Nachstehende Tabelle beinthaltet eine Liste jener Escape-Folgen, welche Ihnen unter PCRE zur Verfügung stehen.


PCRE spezifische Escape-Folge-ZeichenEntsprechung der PCRE spezifischen Escape-Folge-Zeichen
\aPasst zum "Alarm2-Zeichen (HEX 07)
\c XPasst zu Strg-X, wobei X ein beliebiger Buchstabe ist
\ePasst zum Escape-Zeichen (HEX 1B)
\fPasst zum Formfeed-Zeichen (HEX 0C)
\nPasst zum Newline-Zeichen (HEX 0A)
\rPasst zum Carriage Return (HEX 0D)
\tPasst zum Tab-Zeichen (HEX 09)
\dJede Dezimalziffer
\DJedes Zeichen, das keine Dezimalziffer ist
\sJedes Whitespace-Zeichen
\SJedes Zeichen, das kein Whitespace ist
\wJedes "Wort"-Zeichen
\WJedes "Nichtwort"-Zeichen
\bPasst zu einer Wortgrenze
\BPasst, wenn man nicht an einer Wortgrenze ist
\APasst am Anfang eines Objekts
\ZPasst am Ende eines Objekts oder vor dem Zeilenende
\zPasst am Ende eines Objekts
\GPasst an der ersten passenden Position




Suchen nach oktalen Zeichen


Um jetzt oktale Zeichen zu suchen, nutzen Sie einfach das Metazeichen \, gefolgt von der oktalen Nummer betreffenden Metazeichens. Um also beispielsweise nach einem Leerzeichen zu suchen, notieren Sie einfach \40 bzw. \040.

Allerdings handelt es sich hier um einen der Bereiche, bei welchen PCRE etwas uneindeutig sein kann, sofern Sie nicht mit ausreichend Fingerspitzengefühl vorgehen.

Das Metazeichen \ kann selbstverständlich auch für etwaige Rückverweise genutzt werden (also eine Referenz auf ein Muster von PCRE). Beispielswiese \1 stellt einen Rückverweis auf das erste Muster aus einer Liste dar, nicht aber das oktale Zeichen 1.

Um nun nicht unbeabsichtigt mehrdeutig zu sein, ist es klüger, das oktale Zeichen als dreistellige Zahl zu notieren. Im UTF-8-Modus ist 777 die größte erlaubte Zahl.

Alle einstelligen Zahlen nach dem Backslash werden also als Rückverweis angesehen (gewertet), und sofern es mehr als XX Muster gibt, wird \XX überdies als Rückverweis gedeutet. Außerdem kann PCRE auch nach Zeichenketten resp. Zeichen welche im Hexformat notiert sind, suchen. \x0b schaut also nach dem Hexzeichen 0b.

Um nach einer Hexzeichenkette zu schauen, benutzen Sie einfach \x{0b0b....}, die Zeichenkette sollte aber bitte in geschweiften Klammern notiert werden.



Zeicheneigenschaften


Überdies kommt PCRE mit einer ganzen Latte von Funktionen daher, welche nach Zeichen suchen die sozusagen eine bestimmte Eigenschaft aufweisen. Es gibt hier zwei Varianten:
Zum einen die Sprache und zum anderen den Zeichentyp. Um die Varianten jetzt auch korrekt zu nutzen, verwenden Sie die Sequenz \p bzw. \P. Wobei \p nach dem Vorhandensein von einer gegebenen Eigenschaft sucht, und im Umkehrschluß \P jedes Zeichen finden würde, welches diese Eigenschaft eben nicht besitzt.

Wenn Sie jetzt Zeichen suchen möchten, welche zu einer ganz bestimmten Sprache gehören, dann könnten Sie beispielsweise \p{Greek} eintippen, um demzufolge griechische Zeichen zu finden. \P{Greek} würde im Umkehrschluß wiederum auf jedes Zeichen passen, welches somit nicht Teil des griechischen Zeichensatzes ist. Eine komplette Liste aller verfügbaren Sprachen finden Sie u. a. in der entsprechenden Manpage.

Die sonstigen Eigenschaften beziehen sich auf die Attribute eines bestimmten Zeichens (Großbuchstabe, Satzzeichen etc.). Der Großbuchstabe bezieht sich also auf die Hauptgruppe von Zeichen, während die kleinen Buchstaben eine Untergruppe angeben. Wenn nur ein Großbuchstabe übergeben wurde (z. B. \p{L}), dann passen alle Untergruppen.
Nachfolgende Tabelle beinhaltet eine komplette Liste mit Eigenschaftscodes.


PCRE-Eigenschaften-CodesEntsprechung der PCRE-Eigenschaften-Codes
CAnderes
Noandere Ziffer
CcControl
PSatzzeichen
CfFormat
Pcverbindende Satzzeichen
Cnnicht zugewiesen
PdBindestriche und Ähnliches
Coprivate Verwendung
Peschließende Satzzeichen
CsStellvertreter
Pfabschließende Satzzeichen
LBuchstaben
Pistartende Satzzeichen
LlKleinbuchstaben
Poandere Satzzeichen
LmModifikator
Psöffnende Satzzeichen
Loandere Buchstaben
SSymbol
LtTitelbuchstaben
ScWährungssymbol
LuGroßbuchstaben
SkModifikatorsymbol
MMarker
Smmathematisches Symbol
McAbstandsmarker
Soanderes Symbol
Meeinschließender Marker
ZSeparator
MnMarker ohne Breite
ZlZeilentrenner
NZiffer
ZpAbsatztrenner
NdDezimalzahl
ZsAbstandstrenner
Nltextuelle Zahlen



Diese Eigenschaften befähigen Sie somit, robustere Muster mit weniger Zeichen zu formulieren. Wenn pcre händisch kompiliert wird, muss die Konfigurationsoption --enable-unicode-properties benutzt werden, damit sich diese Eigenschaften auch entsprechend benutzen lassen.

Manche libpcre-Pakete (wie bei z. B. Fedora bzw. Debian) beinhalten diese Option (gerade jene für internationale Umgebungen), alle anderen aber leider nicht. Um nun zu checken, ob besagte Eigenschaften in pcre benutzbar sind, tippen Sie z. B. den nachstehenden Code ein:


$ grep -P '\p{Cc}' /bin/ls
grep: support for \P, \p, and \X has not been compiled



Jene Fehlermeldung über die nicht mit einkompilierten Elemente hängt explizit mit pcre zusammen und daher nicht mit grep. Die Lösung des Problems besteht somit darin, jetzt entweder ein geeigneteres Paket zu finden od. selber eines mit den korrekten Optionen zu kompilieren.



PCRE Optionen


Desweitern gibt es noch vier weitere Optionen, welche das Verhalten von PCRE bei der Suche nach Text beeinflussen können: PCRE_CASELESS (i), PCRE_MULTILINE (m), PCRE_DOTALL (s) und PCRE_EXTENDED (x).

PCRE_CASELESS lässt die Muster ganz unabhängig von Groß- und Kleinschreibung passen. Per Standard behandelt PCRE eine Textzeile als eine Zeile, auch wenn dort mehrere \n-Zeichen notiert sind. PCRE_MULTILINE ermöglicht es, solche \n-Zeichen als ein Zeilenende anzusehen (zu werten).

Sofern dann $ od. ^ benutzt wird, so werden die Zeilen auch in Abhängigkeit von \n begutachtet, nicht nur von den echten Zeilenumbrüchen im Suchstring.

PCRE_DOTALL ist dafür zuständig, dass PCRE beim Metazeichen . (Punkt) auch Newline-Zeichen akzeptiert, sofern es hierbei mit "Jokern" sucht. PCRE_EXTENDED ist überaus praktisch, um entsprechende Kommentare in komplizierte Suchstrings einzufügen (welche innerhalb von nicht mit Escape versehenen #-Zeichen stehen).

Um besagte Optionen zu aktivieren, fügen Sie jenes angegebene Optionszeichen einfach innerhalb von Klammern ein, allerdings sollte dabei vor dem Buchstaben unbedingt ein Fragezeichen notiert werden (also dort stehen). Um beispielsweise jetzt ein Muster zu formulieren, welches sodann völlig unabhängig von Groß- und Kleinschreibung nach dem Wort "copyright" sucht, schreiben Sie einfach dieses Muster (wie hier unten vorgemacht):


'(?i)copyright'



Innerhalb von Klammern können die Buchstaben beliebig kombiniert werden. Besagte Optionen können so derart im Suchmuster notiert werden, dass sie lediglich für Teile des Suchstrings gültig sind:
Fügen Sie diese daher einfach am Anfang jenes Stringteils ein, an welchem die Option dann wirksam werden soll.

Um eine Option dann wieder abzuschalten, fügen Sie einfach vor betreffendem Buchstaben ein - (Bindestrich) ein; wie hier unten dargestellt:


'Copy(?i)righ(?-i)t'



So würden also "CopyRIGHt", "CopyrIgHt" und "Copyright" passen, aber nicht "COPYright" od. "CopyrighT".


'(?imsx)copy(?-sx)right'



Gemäß diesem Beispiel würden also alle behandelten PCRE-Optionen gesetzt werden, jedoch nach Erreichen des Zeichens "r" würden PCRE_DOTALL und PCRE_EXTENDED wiederum abgeschaltet werden. Wenn Sie jetzt also meinen, das reguläre Ausdrücke im Perl-Stil ziemlich komplex sind, dann liegen Sie mit Ihrer Annahme natürlich richtig.

Es gibt selbstverständlich noch sehr viel mehr, als bloß dass was hier erklärt wurde ..., dass sollte nun aber auch für's erste reichen. Die (nicht zu verleugnenden) Nachteile von PCRE sind natürlich ganz klar:

1. Die sehr hohe Komplexität.
2. Die häufig entstehenden Mehrdeutigkeiten.



GNU Grep Recipes


Nützliche Code Snippets


Hier ein kurzer Überblick über ein paar klasse grep-Rezepte. Weil perl-basierte reguläre Ausdrücke leider nicht überall verfügbar sind, wird diese Liste lediglich die erweiterten regulären Ausdrücke von grep behandeln obschon Perl hierbei meist schneller wäre.

Es ist daher nicht wirklich klug, diese Kommandos auf der Kommandozeile einzutippen und damit per Standardausgabe auf dem Bildschirm auszugeben, wenn es sich dabei um sehr vertrauliche Informationen handelt, welche auf einer Partition zu finden sind. Sehr viel schlauer ist es dann doch eher, einfach die Optionen -l und -r zu verwenden, um damit rekursiv zu suchen und darüber hinaus anstelle der gefundenen Zeilen lediglich die betreffenden Dateinamen auszuspucken in welchen es entsprechende Treffer gab.

Bei den meisten Rezepten ist es zudem auch ganz sinnvoll, \b vor und nach der Zeichenkette einzufügen. So ist dann auch garantiert sichergestellt, dass der Inhalt auch wirklich ein Whitespace vor und nach dem Treffer beinhaltet. Andernfalls würden Sie nämlich Gefahr laufen z. B. eine 29-stellige Zahl anstelle eine 9-stelligen zu finden etc.!

Sie können jetzt diese Muster (od. auch andere) in eine Datei schreiben und sodann als Eingabeliste an grep übergeben, so dass nach jenen möglichen Mustern simultan gesucht wird.



IP-Adressen


$ grep -E '\b[0-9]{1,3}(\.[0-9]{1,3}){3}\b' patterns

123.24.45.67
312.543.121.1



Dieses Muster ist Ihnen dabei behilflich, IP-Adressen aus Dateien rauszufiltern. Anstatt [0-9] könnten Sie aber auch [:digit:] verwenden - hiermit erreichen Sie eine höhere Lesbarkeit. Die meisten Benutzer möchten aber sehr warscheinlich lieber etwas weniger tippen und vernachlässigen demgegenüber die Lesbarkeit.

Mit dem Muster hier werden jetzt auch Zeichenketten gefunden, welche keine validen IP-Adressen darstellen, wie beispielsweise der zweite Eintrag in der Beispielliste. Reguläre Ausdrücke arbeiten mit einzelnen Zeichen, und es gibt meines Erachtens nach daher keinen geeigneteren Weg, grep klar zu machen, nur nach den Werten 1-255 zu schauen. Hier kann es natürlich aber auch falsche Übereinstimmungen (Treffer) geben.

Hier eine kniffligere Form, welche garantiert, dass eben keine falschen Treffer gefunden werden. Das könnte wie folgt notiert werden:


$ grep -E '\b((25[0-5]|2[0-4][0-9]|[01]? [0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]| [01]?[0-9][0-9]?)\b' patterns



In diesem Fall wird dafür Sorge getragen, dass wirklich alle IP-Adressen welche einem Oktett zwischen 0 und 255 haben auch entsprechend gefunden werden. Dies wird durch eine sinnvolle Kombination von div. Mustern erreicht. So werden also unter Garantie lediglich IP-Adressen gefunden; leider wird das Muster dadurch bedingt etwas komplexer und die Performance ist nicht so prickelnd.



MAC-Adressen


$ grep -Ei '\b[0-9a-f]{2} (:[0-9a-f]{2}){5}\b' patterns

ab:14:ed:41:aa:00



Hier wird nun die Option -i verwendet, so dass Groß- und Kleinschreibung entsprechend ignoriert werden. Genauso wie beim IP-Rezept könnte man natürlich auch hier [:xdigit:] anstatt der Zeichenklasse [0-9a-f] benutzen; zumindest wenn man großen Wert auf bessere Lesbarkeit legt.


E-Mail-Adressen


$ grep -Ei '\b[a-z0-9]{1,}@*\. (com|net|org|uk|mil|gov|edu)\b' patterns

test@some.com
test@some.edu
test@some.co.uk



Die hier gezeigte Liste ist lediglich eine Untermenge von Top-Level-Domains, welche bei uns gut funktionieren. Wenn also beispielsweise jemand bloß nach US-Adressen suchen möchte, macht der .uk-Eintrag allerdings überhaupt keinen Sinn mehr.

Eventuell ist es aber auch Ihr erklärtes Ziel, ganz offensichtliche Spammer in Maillogs ausfindig zu machen; in dem Fall würde es sich natürlich geradezu anbieten, nach der Top-Level-Domain .info zu suchen (wir haben nämlich noch niemanden getroffen, der von solchen Domains erwünschte E-Mails bekommt).

Das Muster hier sollte aber bloß als Ausgangspunkt für Ihre persönlichen Modifikationen verwendet werden.



Telefonnummern in den USA


$ grep -E '\b(\(|)[0-9]{3} (\)|-|\)-|)[0-9]{3}(-|)[0-9]{4}\b' patterns

(312)-555-1212
(312) 555-1212
312-555-1212
3125551212



Das Muster hier ist allerdings ein wenig komplizierter und zwar aus dem einfachen Grunde dass die US-Telefonnummern ganz unterschiedlich aussehen können.

Es können also Leerzeichen, Striche, Klammern od. auch einfach nichts außer den Zahlen selbst in der gesuchten Zeichenkette enthalten sein.



Sozialversicherungsnummern in den USA


$ grep -E '\b[0-9]{3}( |-|) [0-9]{2}( |-|)[0-9]{4}\b' patterns

333333333
333 33 3333
333-33-3333



Bekanntlich sind Sozialversicherungsnummern in den USA nunmal der Schlüssel zur Identität einer Person, vor diesem Hintergrund wird ihre Nutzung (logischerweise) zunehmend massiv eingeschränkt.

Mittlerweile durchsuchen ziemlich viele Organisationen mithilfe von Werkzeugen wie Spider (etc.) aktiv alle Dateien eines Systems, um besagte Sozialversicherungsnummern auszumachen. Dieses Werkzeug ist aber prinzipiell nicht mehr und nicht weniger als bloß eine simple Liste dieser hier gezeigten grep -Rezepte.

Das Muster ist - im Übrigen - um einiges simpler als jenes für die Telefonnummern.



Kreditkartennummern


Für viele Kreditkartennummern kann von Ihnen dieser Ausdruck notiert werden:


$ grep -E '\b[0-9]{4}(( |-|) [0-9]{4}){3}\b' patterns

1234 5678 9012 3456
1234567890123456
1234-5678-9012-3456



American Express Kartennummern findet man so:


$ grep -E '\b[0-9]{4}( |-|) [0-9]{6}( |-|)[0-9]{5}\b' patterns

1234-567890-12345
123456789012345
1234 567890 12345



Es gibt zwei Versionen, denn American Express verwendet ein etwas differenzierteres Muster als die restlichen Kartenfirmen.

Die grundlegende Idee bleibt jedoch gleich:
Die Suche nach Zifferngruppen, welche auf das allgemeine Muster einer Kreditkarte passen.



Copyrightgeschütztes resp. vertrauliches Material


Viele Firmen bzw. Organisationen benutzen für interne Daten Klassifikationen, durch welche leicht zu bestimmen ist, ob jemand nun berechtigt ist, diese zu lesen oder eben nicht.

Die meisten Dateiformate sind bei Texten aber leider keine reinen ASCII-Dateien, trotzdem lässt sich der betreffende Text dennoch finden (meistens jedenfalls). So könnten Sie beispielsweise grep verwenden, um nach dem Vorkommen von bestimmten Zeichenketten in Word-Dateien zu suchen; selbst wenn sich jene Dateien nicht einfach in einem Konsolenfenster anzeigen lassen.

Wenn Ihre Firma beispielsweise die Auszeichnung "ACME Corp.-Proprietary and Confidential" verwendet, könnten Sie mit dem diesem Kommando Dateien suchen, welche eben diesen Inhalt haben:


fgrep -l 'ACME Corp. - Proprietary and Confidential' patterns



Durchsuchen sehr vieler Dateien


Ebenso wie zahlreiche andere Konsolenkommandos arbeitet auch das Kommando grep eine ziemlich große Anzahl von Dateien mit einem Aufruf ab. So durchsucht grep sometext * jede Datei im aktuellen Verzeichnis nach "sometext".

Allerdings gibt es hier auch eine Höchstmenge von Dateien, welche in einem einzigen Aufruf abgearbeitet werden können. Wenn Sie grep also jetzt anweisen, zu viele Dateien auf einmal abzuarbeiten, bekommen Sie natürlich die entsprechende Fehlermeldung "Too Many Files" od. einen ähnlichen Text (kommt ganz auf Ihre Shell an).

Ein Werkzeug namens xargs kann besagte Limitierung eliminieren.

Um jetzt aber jede Datei auf einem System auf die Zeichenkette "ABCDEFGH" zu checken, müssten Sie auch dieses Kommando (hier unten) eintippen:


find / -print | xargs grep 'ABCDEFGH'



Damit wird dann jede Datei auf dem Computer auf die Zeichenkette "ABCDEFGH" geprüft, dabei stolpert man nicht über die nervigen Fehlermeldungen, welche immer dann auftreten, wenn zu viele Dateien geöffnet worden sind. Meistens ist diese Grenze schon allein durch den Kernel vorgegeben, dieser erlaubt nämlich lediglich eine limitierte Anzahl von Memory-Seiten für Befehlszeilenargumente.

Bevor Sie jetzt allerdings auf die glorreiche Idee kommen, den Kernel deswegen neu zu kompilieren, um ihm sodann einen größeren Wert mitzugeben, verwenden Sie doch lieber xargs.


Zeichenketten über mehrere Zeilen hinweg finden


Auch wenn viele grep-Versionen beim Verarbeiten von mehreren Zeilen nicht so gut zu handhaben sind, so lassen sich solche Probleme dennoch mittels grep -P im Multizeilenmodus geschickt umschiffen.

Werfen Sie mal einen Blick auf nachstehendes Beispiel:


red dog


Gewöhnliche grep-Tricks also auch die Einfügung eines Newline-Zeichens werden nicht von Erfolg gekrönt sein sofern Sie beabsichtigen sollten eine Zeichenkette zu finden welche sich - wie hier - über 2 Zeilen erstreckt ("red" gefolgt von "dog").


$ grep -E 'red\ndog' test
$ grep -G 'red\ndog' test
$ grep -F 'red\ndog' test



bei PCRE_MULTILINE in Verwendung mit grep -P klappt es dann aber doch:


$ grep -P '(?m)red\ndog' test

red
dog



Damit können Sie jene Beschränkung von grep umschiffen, aufgrund welcher es Ihnen nun nicht möglich ist, gleichzeitig mehr als nur eine einzige Zeile zu durchsuchen. Das ist dann wohl auch einer der zahlreichen Gründe, weshalb grep -P viel eher für die mächtigeren Suchaufgaben verwendet wird.

Schließlich soll jetzt nicht unerwähnt bleiben, dass auf div. Websites bzw. Foren sehr warscheinlich jemand bereits einen entsprechenden regulären Ausdruck veröffentlicht hat welcher auch gut geeignet ist an Ihre expliziten Bedürfnisse angepasst zu werden. Ihre Möglichkeiten sind also quasi unbegrenzt.

Anzumerken sei im Übrigen noch, dass es zwischen grep -G, grep -E und grep -P keine nennenswerten Performanceunterschiede gibt, es hängt also maßgeblich davon ab wie gut Ihr regulärer Ausdruck formuliert ist.

Wie bereits erwähnt, ist grep überdies dazu befähigt auf ziemlich raffinierte Art und Weise Dateien zu durchforsten. Es ist selbstverständlich auch möglich, längst gefundene Übereinstimmungen zu benutzen, um nach weiter hinten liegenden Zeichenketten zu suchen (sog. Rückverweise bzw. Backreferences).

Es gibt zudem eine ganze Latte von Tricks, um auch nach nicht zu veröffentlichenden persönlichen Informationen zu suchen resp. sogar um Binärstrings in Binärdateien zu finden.



Rückverweise


Das Programm grep hält die Möglichkeit bereit, basierend auf verschiedenen vorherigen Bedingungen nach Zeichenketten zu suchen. Wenn Sie also beispielsweise all jene Zeilen finden möchten, welche eine ganz bestimmte Gruppe von Wörtern wiederholt beinhalten, so würde hier ein simples grep-Muster nicht funktionieren, es ist aber möglich, dafür entsprechende Rückverweise zu nutzen. Stellen Sie sich einfach vor, Sie möchten alle Zeilen finden, in denen die Wörter "red", "blue" od. "green" mehrfach enthalten sind.

Betrachten Sie dieses Beispiel:


The red dog fetches the green ball.
The green dog fetches the blue ball.
The blue dog fetches the blue ball.


Lediglich in der dritten Zeile wird dieselbe Farbe wiederholt. Ein regulärer Ausdruck wie ''(red|green|blue)*(red|green|blue)'' würde jetzt also alle drei Zeilen ausgeben.

Um das Problem zu umgehen, könnten Sie also Rückverweise verwenden:


grep -E '(red|green|blue).*\1' filename



Bei dieser Anweisung hier wird jetzt lediglich die dritte Zeile gefunden, so wie es dann eigentlich auch gewünscht war. Bei erweiterten regulären Ausdrücken kann aber lediglich eine einzelne Ziffer zur Angabe eines Rückverweises notiert werden (Sie können sich demnach also höchstens auf beispielsweise den neunten Rückverweis beziehen). Bei regulären Ausdrücken im Perl-Stil können Sie rein theoretisch sehr viel mehr Rückverweise verwenden (also mind. zweistellig).

Das hier lässt sich auch sehr gut nutzen, um sowohl die XML-Syntax zu überprüfen (also um zu checken, ob die Auszeichnung korrekt gesetzt sind), als auch um HTML-Code entsprechend zu validieren (resp. "Überschriften"-Tags wie <h1>, <h2> etc. zu vergleichen), od. sogar, um einen Text auf unnötige Wiederholungen hin zu prüfen. Es ist daher auch sehr wichtig, dass Sie Rückverweise unbedingt in Klammern notieren, um entsprechende Verweisnummern zu bestimmen.

grep liest also das Suchmuster von links nach rechts ein und nummeriert dann das erste gefundene Untermuster in entsprechenden Klammern mit der 1.

Oft werden Backreferences genutzt, wenn ein Untermuster Alternationen beinhaltet, genau so wie im eben gezeigten Beispiel. Trotzdem muss ein Untermuster jetzt nicht zwingend Alternationen beinhalten.

Angenommen Sie haben ein großes Untermuster auf welches Sie sich nachher noch beziehen möchten, so könnten Sie einfach eine Backreference als "Alias" für besagtes Untermuster verwenden und zwar ohne dass das komplette Muster hierzu mehrfach eingeben werden müsste. In diesem Kontext sollten Sie das folgende Beispiel studieren:


grep -E '(I am the very model of a modern major general.).*\1' filename



So würde also nach jenen Wiederholungen des Satzes "I am the very model of a modern major general." gesucht werden. So spart man sich logischerweise viel Tipparbeit, und überdies lässt sich der reguläre Ausdruck sehr viel einfacher handhaben; allerdings sollte man natürlich immer darauf achten das darunter die Performance nicht zu sehr leidet. Der Nutzer muss daher Bequemlichkeit und Performance entsprechend gegeneinander abwägen.



Suchen in Binärdateien


Man kann grep nicht nur zum Durchsuchen von Textdateien nach Textstrings verwenden - nein, grep hat noch mehr auf dem Kasten. Es ist überdies nämlich auch möglich grep in Binärdateien nach div. Zeichenketten suchen zu lassen.

Vor diesem Hintergrund sei auch darauf hingewiesen, dass sich (in diesem Kontext) die Daseinsberechtigung von "Text"-Dateien damit begründen lässt dass selbige für Menschen problemlos lesbar sind. Computer hingegen lieben Binär- und Maschinencode. Der komplette ASCII-Zeichensatz besteht aus 255 Zeichen, davon sind aber lediglich in etwa 60 (Zeichen) für Menschen lesbar.

Trotzdem beinhalten viele Computerprogramme auch Textstrings, beispielsweise "help"-Bildschirme, Dateinamen, Fehlermeldungen etc. Dem Kommando grep ist es aber auch relativ egal ob Sie es nun für die Suche in Text- oder Binärdateien gebrauchen. Hauptsache Sie geben ihm ein entsprechendes Muster (auch Binärmuster sind ok); so wird grep munter jede Datei durchsuchen, die Sie ihm auftischen.

grep führt im Übrigen nur eine erste Prüfung durch, um zu schauen, ob die Datei nun binär ist oder eben nicht; grep wird den Output der Resultate sodann entsprechend anpassen (außer Sie haben ihm ein anderes Verhalten auferlegt):


bash $ grep help /bin/ls

Binary file /bin/ls matches



Dieses Kommando sucht nach der Zeichenkette "help" in der Binärdatei ls. Statt also jene Zeile auszugeben, in welcher der gefundene Text notiert ist, weist es Sie lediglich darauf hin, dass es hier eine Übereinstimmung (Treffer) gegeben hat.

In Binärdateien gibt es keine Zeilenumbrüche, weil diese den Code signifikant verändern würden - sie dienen lediglich zur besseren Lesbarkeit. Deshalb teilt Ihnen grep lediglich mit, dass es Übereinstimmungen (Treffer) gab.

Um sich einen kurzen Überblick darüber zu verschaffen, welchen Text eine Binärdatei beinhaltet, können Sie das Kommando strings verwenden. So würde also beispielsweise strings /bin/ls alle Textstrings im Kommando ls auflisten. Aber es gibt noch eine andere Möglichkeit Binärdateien zu durchsuchen, welche hierfür wohl besser geeignet ist. Hierfür müssen Sie aber auf ein paar kleine Tricks zurückgreifen, denn mit einer handelsüblichen Tastatur können Sie Binärdaten nicht direkt eintippen.

Sie benötigen also eine spezielle Form des regulären Ausdrucks, um das hexadezimale Äquivalent der von Ihnen gesuchten Daten einzugeben. Wenn Sie also beispielsweise eine Binärdatei auf die hexadezimalen Werte ABAA hin prüfen möchten, so können Sie das nachstehende Kommando nutzen:


bash $ grep '[\xabaa]' test.hex

Binary file test.hex matches



Im Normalfall geben Sie einfach \x und danach die hexadezimale Zeichenkette ein, welche es zu finden gilt. Dabei gibt es keine Längenbeschränkung. Diese Form der Suche kann bei der Analyse von Malware ganz praktisch sein. So kann beispielsweise das Metasploit Framework (http://www.metasploit.org) binäre Payloads erzeugen, um entfernte Computer zu infizieren. Dieses Payload könnte verwendet werden, um eine Remote-Shell zu erzeugen, Benutzerkonten hinzuzufügen oder andere schlimme Dinge zu machen.

Mit der hexadezimalen Suche ist es also kein Problem, mithilfe von Binärzeichenketten zu checken, welcher der Metasploit-Payloads bei einem Angriff benutzt wurde. Und wenn Sie dann eine eindeutige hexadezimale Zeichenkette aus einem Virus bestimmen konnten, ist es überdies möglich, einen einfachen Virenscanner mit grep zu bauen. Viele ältere Virenscanner nämlich haben (in etwa) genau das getan - also nach eindeutigen Binärzeichenketten (bekannter bösartiger hexadezimaler Signaturen) gesucht.

Diverse Pufferüberläufe bzw. Exploit-Payloads sind nunmal in C geschrieben, und in C ist es überdies auch üblich, jede hexadezimale Zahl mit dem Escape \x zu notieren. Sehen Sie sich mal den folgenden Exploit-Payload (Pufferüberlauf) an:


"\xeb\x17\x5e\x89\x76\x08\x31
\xc0\x88\x46\x07\x89\x46\x0c
\xb0\x0b\x89\xf3\x8d\x4e\x08
\x31\xd2\xcd\x80\xe8\xe4\xff
\xff\xff\x2f\x62\x69\x6e\x2f
\x73\x68\x58";



Der eben vorgestellte Exploit funktioniert bei Red Hat 5 bzw. 6 (nicht aber bei Enterprise Red Hat), daher ist dieser spezielle Code (in dem Fall) für die Tonne, aber dennoch ist es nicht sonderlich schwierig, aktuelleren Exploit-Code zu finden. Wissenswert ist zudem, dass diese Methodik nicht hinhaut, wenn man Dateien durchforstet, welche als Textdateien erkannt werden.

Die Suche nach hexadezimalen Zeichenketten funktioniert lediglich bei Dateien, die grep dann auch als Binärdateien erkennt.



Terms


Legal Disclaimer


Inhaltshaftung


Wir sind als (Dienste-)Anbieter nach Intention d. § 7 Abs.1 TMG f. d. eigenen Inhalte auf diesen (Web-)Seiten (ledigl.) entspr. d. derzeitig vorherrschenden allgem. Gesetze(-slage) verantwortlich.

Nach Entsprechung d. §§ 8-10 TMG sind wir als Dienstleister jedoch mitnichten verpflichtet, übermittelte resp. gespeicherte fremde Informationen zu überwachen bzw. nach evtl. etwaigen Umständen zu forschen, welche ggf. auf eine rechtswidrige Tätigkeit hinweisen (könnten).

Überdies bleiben hiervon (jedwede evtl. rechtl.) Verpflichtungen z. Entfernung (Löschung) resp. Sperrung v. Informationsnutzungen (nach d. allgem. gültigen Gesetzen) unberührt. Allerdings ist eine evtl. diesbzgl. Haftung erst ab jenem Zeitpunkt möglich, ab welchem wir Kenntnis von einer konkreten Rechtsverletzung erlangt haben.

Bei Bekanntwerden v. entspr. (also konkreten) Rechtsverletzungen werden wir selbstverständlich (unverzüglich) betreffende Inhalte entfernen (löschen).


Linkhaftung


Unser Internetauftritt beinhaltet überdies auch Links zu ext. Websites Dritter, auf deren Inhalte wir natürlich keinen Einfluss haben. Selbstverständlich können wir f. besagte fremde Inhalte auch keine diesbzgl. Haftung (Gewähr) übernehmen.

Für jedwede Inhalte betreffender verlinkter (Web-)Seiten ist also ausschließlich d. jeweilige Dienstleister resp. Betreiber d. Seiten verantwortlich.

Jene verlinkten (Web-)Seiten wurden (z. Zeitpunkt ihrer Verlinkung) auf evtl. Rechtsverstöße hin geprüft. Rechtswidrige Inhalte waren jedoch z. Zeitpunkt d. Verlinkung für uns nicht erkennbar. Eine permanente inhaltl. Kontrolle jener verlinkten (Web-)Seiten ist allerdings ohne konkrete Anhaltspunkte einer entspr. Rechtsverletzung weder zumutbar noch legitim.

Bei Bekanntwerden v. entspr. Rechtsverletzungen werden wir natürlich derartige Links sofortig löschen.



Urheberrecht


Jene durch d. (Seiten-)Betreiber erstellten Inhalte resp. Werke auf diesen Websites unterliegen dem deutschem Urheberrecht. Eine Vervielfältigung, Bearbeitung, Verbreitung resp. jedwede Art d. Verwertung außerhalb d. Grenzen d. Urheberrechtes bedürfen (daher zwingend) einer schriftl. Zustimmung d. betreffenden Autors resp. Erstellers.

Downloads u. / od. Kopien dieser Seite sind somit lediglich f. d. privaten, also den nicht kommerziellen Gebrauch gestattet. Soweit Inhalte auf dieser Website nicht v. Betreiber erstellt wurden, werden betreffende Urheberrechte Dritter entspr. beachtet. Insbesondere werden etwaige Inhalte Dritter auch als solche gekennzeichnet.

Sollten Sie aber trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, so bitten wir Sie höflich und respektvoll um einen entspr. Hinweis. Bei Bekanntwerden v. Rechtsverletzungen werden wir derartige Inhalte natürlich unverzüglich löschen.



Data Protection


Datenschutz


Eine Nutzung unserer Website ist i. d. R. auch ohne die Angabe personenbezogener Daten möglich. Soweit auf unseren (Web-)Seiten also personenbezogene Daten (beispielsweise Name, Anschrift bzw. Email-Adressen) erhoben werden (sollten), erfolgt dies ausschließlich, soweit dies möglich ist, konsequent auf freiwilliger Basis. Jene Daten werden somit ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.

Wir weisen überdies explizit darauf hin, d. d. Datenübertragung im Internet (z.B. bei d. Kommunikation via Email) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz d. Daten v. d. Zugriff durch Dritte ist demgemäß zu keinem Zeitpunkt garantiert.

Der Nutzung v. im Rahmen d. Impressumspflicht veröffentlichten Kontaktdaten durch Dritte z. Übersendung v. nicht ausdrückl. angeforderter Werbung u. Informationsmaterialien (etc.) wird hiermit ausdrückl. widersprochen.

Die Betreiber d. Seiten behalten sich daher überdies ausdrückl. rechtl. Schritte im Falle d. unverlangten Zusendung v. Werbeinformationen, wie etwa durch Spam-Mails, (etc.) vor; (z. B. eine evtl. Übermittlung betreffenden Sachverhaltes an d. jeweils zuständigen Strafvervolgungsbehörden).



Contact / Imprint




Carrier / Contact (Angaben i. S. d. § 5 TMG; resp. verantwortl. - f. journal.-redakt. Inhalte - gem. § 55 Abs. 2 RStV):


Home Address:
Sascha Kühl  |  Detmolder Straße 317  |  33 175 Bad Lippspringe

P.O. Box:
Sascha Kühl  |  Postfach 14 03  |  33 169 Bad Lippspringe                                                                                                    


Phone:
0049.(0)1578.719 2486

Fax:
0049.(0)3222.640 7132

Email:
webmaster@grepmaster.eu




Empfänger:
Sascha Kühl

IBAN:
DE48 7002 2200 0072 3457 62

BIC:
FDDODEMMXXX

Kreditinstitut:
Fidor Bank AG

Verwendungszweck:
Spende www.grepmaster.eu