Fatmawati Achmad Zaenuri/Shutterstock
Sie fragen sich, was diese seltsamen Symbolketten unter Linux bewirken? Sie geben Ihnen Kommandozeilen-Magie! Wir zeigen Ihnen, wie Sie mit regulären Ausdrücken Zaubersprüche anwenden und Ihre Kommandozeilen-Fähigkeiten verbessern.
Was sind reguläre Ausdrücke?
Reguläre Ausdrücke (Regexes) sind eine Möglichkeit, passende Zeichenfolgen zu finden. Sie verwenden Buchstaben und Symbole, um ein Muster zu definieren, nach dem in einer Datei oder einem Stream gesucht wird. Es gibt verschiedene Geschmacksrichtungen von Regex. Wir werden uns die Version ansehen, die in gängigen Linux-Dienstprogrammen und -Befehlen verwendet wird, wie z grep
, der Befehl, der druckt Zeilen, die einem Suchmuster entsprechen. Das ist ein bisschen anders als mit Standard-Regex im Programmierkontext.
Über Regexes wurden ganze Bücher geschrieben, daher ist dieses Tutorial nur eine Einführung. Es gibt grundlegende und erweiterte Regexes, und wir werden hier die erweiterten verwenden.
So verwenden Sie die erweiterten regulären Ausdrücke mit grep
, du musst die verwenden -E
(erweiterte) Option. Denn das wird sehr schnell langweilig, die egrep
Befehl erstellt wurde. Die egrep
Befehl ist derselbe wie der grep -E
Kombination, Sie müssen die einfach nicht verwenden -E
Option jedes Mal.
Wenn Sie es bequemer finden egrep
, du kannst. Beachten Sie jedoch, dass es offiziell veraltet ist. Es ist immer noch in allen Distributionen vorhanden, die wir überprüft haben, aber es könnte in Zukunft verschwinden.
Natürlich können Sie jederzeit Ihre eigenen Aliase erstellen, sodass Ihre bevorzugten Optionen immer für Sie enthalten sind.
Von kleinen Anfängen
Für unsere Beispiele verwenden wir eine reine Textdatei, die eine Liste von Geeks enthält. Denken Sie daran, dass Sie mit vielen Linux-Befehlen Regexes verwenden können. Wir benutzen nur grep
als bequeme Möglichkeit, sie zu demonstrieren.
Hier der Inhalt der Datei:
less geek.txt

Der erste Teil der Datei wird angezeigt.

Beginnen wir mit einem einfachen Suchmuster und durchsuchen die Datei nach Vorkommen des Buchstabens „o“. Nochmal, weil wir die verwenden -E
(erweiterte Regex) in allen unseren Beispielen geben wir Folgendes ein:
grep -E 'o' geeks.txt

Jede Zeile, die das Suchmuster enthält, wird angezeigt und der passende Buchstabe wird hervorgehoben. Wir haben eine einfache Suche ohne Einschränkungen durchgeführt. Dabei spielt es keine Rolle, ob der Buchstabe mehrmals, am Ende der Zeichenfolge, zweimal im selben Wort oder sogar neben sich vorkommt.
Ein paar Namen hatten doppelte O’s; Wir geben Folgendes ein, um nur diese aufzulisten:
grep -E 'oo' geeks.txt

Unsere Ergebnismenge ist erwartungsgemäß viel kleiner und unser Suchbegriff wird wörtlich interpretiert. Es bedeutet nichts anderes als das, was wir eingegeben haben: doppelte „o“-Zeichen.
Im weiteren Verlauf werden wir mit unseren Suchmustern mehr Funktionalität sehen.
Zeilennummern und andere grep-Tricks
Falls Sie es wollen grep
um die Zeilennummer der passenden Einträge aufzulisten, können Sie die -n
(Zeilennummer) Option. Das ist ein grep
Trick – er ist nicht Teil der Regex-Funktionalität. Manchmal möchten Sie jedoch möglicherweise wissen, wo sich in einer Datei die übereinstimmenden Einträge befinden.
Wir geben folgendes ein:
grep -E -n 'o' geeks.txt

Noch ein handliches grep
Trick, den Sie verwenden können, ist der -o
(nur passende) Option. Es zeigt nur die passende Zeichenfolge an, nicht den umgebenden Text. Dies kann nützlich sein, wenn Sie eine Liste schnell nach doppelten Übereinstimmungen in einer der Zeilen durchsuchen müssen.
Dazu geben wir Folgendes ein:
grep -E -n -o 'o' geeks.txt

Wenn Sie die Leistung auf das Nötigste reduzieren möchten, können Sie die -c
(zählen) Option.
Wir geben Folgendes ein, um die Anzahl der Zeilen in der Datei anzuzeigen, die Übereinstimmungen enthalten:
grep -E -c 'o' geeks.txt

Der Wechseloperator
Wenn Sie nach Vorkommen sowohl des doppelten „l“ als auch des doppelten „o“ suchen möchten, können Sie die Pipe (|
) Zeichen, das der Alternationsoperator ist. Es sucht nach Übereinstimmungen für das Suchmuster links oder rechts davon.
Wir geben folgendes ein:
grep -E -n -o 'll|oo' geeks.txt

Jede Zeile, die ein doppeltes „l“, „o“ oder beides enthält, wird in den Ergebnissen angezeigt.
Groß-/Kleinschreibung
Sie können auch den Alternation-Operator verwenden, um Suchmuster wie folgt zu erstellen:
am|Am
Dies wird sowohl mit «am» als auch mit «Am» übereinstimmen. Bei allen anderen als trivialen Beispielen führt dies schnell zu umständlichen Suchmustern. Eine einfache Möglichkeit, dies zu umgehen, ist die Verwendung der -i
(Groß-/Kleinschreibung ignorieren) Option mit grep
.
Dazu geben wir Folgendes ein:
grep -E 'am' geeks.txt
grep -E -i 'am' geeks.txt

Der erste Befehl erzeugt drei Ergebnisse mit drei hervorgehobenen Übereinstimmungen. Der zweite Befehl führt zu vier Ergebnissen, da das „Am“ in „Amanda“ ebenfalls eine Übereinstimmung ist.
Verankerung
Wir können die „Am“-Sequenz auch auf andere Weise abgleichen. Beispielsweise können wir gezielt nach diesem Muster suchen oder die Groß-/Kleinschreibung ignorieren und angeben, dass die Sequenz am Anfang einer Zeile stehen muss.
Wenn Sie Sequenzen abgleichen, die an einem bestimmten Teil einer Zeichenzeile oder eines Wortes erscheinen, wird dies als Ankern bezeichnet. Sie verwenden die Einfügemarke (^
) Symbol zur Angabe des Suchmusters sollte eine Zeichenfolge nur dann als Übereinstimmung betrachten, wenn sie am Anfang einer Zeile steht.
Wir geben Folgendes ein (beachten Sie, dass sich das Caret in den einfachen Anführungszeichen befindet):
grep -E ‘Bin’ geeks.txt
grep -E -i '^am' geeks.txt

Beide Befehle stimmen mit „Am“ überein.
Suchen wir nun nach Zeilen, die ein doppeltes „n“ am Ende einer Zeile enthalten.
Wir geben Folgendes mit einem Dollarzeichen ($
) um das Ende der Zeile darzustellen:
grep -E -i 'nn' geeks.txt
grep -E -i 'nn$' geeks.txt

Platzhalter
Sie können einen Zeitraum ( .
), um ein beliebiges einzelnes Zeichen darzustellen.
Wir geben Folgendes ein, um nach Mustern zu suchen, die mit „T“ beginnen, mit „m“ enden und ein einzelnes Zeichen dazwischen haben:
grep -E 'T.m' geeks.txt

Das Suchmuster stimmte mit den Sequenzen „Tim“ und „Tom“ überein. Sie können die Punkte auch wiederholen, um eine bestimmte Anzahl von Zeichen anzugeben.
Wir geben Folgendes ein, um anzuzeigen, dass es uns egal ist, was die mittleren drei Zeichen sind:
grep-E 'J...n' geeks.txt

Die Zeile mit „Jason“ wird abgeglichen und angezeigt.
Verwenden Sie das Sternchen (*
), um null oder mehr Vorkommen des vorhergehenden Zeichens zu finden. In diesem Beispiel ist das Zeichen vor dem Stern der Punkt (.
), was (wieder) ein beliebiges Zeichen bedeutet.
Dies bedeutet das Sternchen (*
) entspricht einer beliebigen Anzahl (einschließlich null) von Vorkommen eines beliebigen Zeichens.
Das Sternchen ist für Regex-Neulinge manchmal verwirrend. Dies liegt vielleicht daran, dass sie es normalerweise als Platzhalter verwenden, der «alles» bedeutet.
In Regexes hingegen 'c*t'
stimmt nicht mit «Katze», «Kinderbett», «Blässhuhn» usw. überein. Stattdessen bedeutet es «entspricht null oder mehr ‘c’-Zeichen, gefolgt von einem ‘t’.» Es stimmt also mit „t“, „ct“, „cct“, „ccct“ oder einer beliebigen Anzahl von „c“-Zeichen überein.
Da wir das Format des Inhalts in unserer Datei kennen, können wir als letztes Zeichen im Suchmuster ein Leerzeichen hinzufügen. Ein Leerzeichen erscheint in unserer Datei nur zwischen dem Vor- und Nachnamen.
Wir geben also Folgendes ein, um zu erzwingen, dass die Suche nur die Vornamen aus der Datei enthält:
grep -E 'J.*n ' geeks.txt
grep -E 'J.*n ' geeks.txt

Auf den ersten Blick scheinen die Ergebnisse des ersten Befehls einige ungerade Übereinstimmungen zu enthalten. Sie entsprechen jedoch alle den Regeln des von uns verwendeten Suchmusters.
Die Sequenz muss mit einem großen „J“ beginnen, gefolgt von einer beliebigen Anzahl von Zeichen und dann einem „n“. Obwohl alle Übereinstimmungen mit «J» beginnen und mit einem «n» enden, sind einige von ihnen nicht das, was Sie vielleicht erwarten.
Da wir das Leerzeichen im zweiten Suchmuster hinzugefügt haben, haben wir das bekommen, was wir wollten: alle Vornamen, die mit „J“ beginnen und auf „n“ enden.
Charakterklassen
Nehmen wir an, wir möchten alle Zeilen finden, die mit einem großen „N“ oder „W“ beginnen.
Wenn wir den folgenden Befehl verwenden, entspricht er jeder Zeile mit einer Sequenz, die entweder mit einem großen „N“ oder „W“ beginnt, unabhängig davon, wo sie in der Zeile erscheint:
grep -E 'N|W' geeks.txt
Das ist nicht das, was wir wollen. Wenn wir den Zeilenanfangsanker (^
) am Anfang des Suchmusters, wie unten gezeigt, erhalten wir die gleichen Ergebnisse, jedoch aus einem anderen Grund:
grep -E '^N|W' geeks.txt

Die Suche findet Zeilen, die ein großes „W“ enthalten, an einer beliebigen Stelle in der Zeile. Es stimmt auch mit der Zeile „No more“ überein, da es mit einem großen „N“ beginnt. Der Zeilenanfangsanker (^
) wird nur auf den Großbuchstaben „N“ angewendet.
Wir könnten auch einen Zeilenanfangsanker zum Großbuchstaben „W“ hinzufügen, aber das würde bei einem Suchmuster, das komplizierter ist als unser einfaches Beispiel, bald ineffizient werden.
Die Lösung besteht darin, einen Teil unseres Suchmusters in Klammern ([]
) und wenden Sie den Ankeroperator auf die Gruppe an. Die Klammern ([]
) bedeutet „beliebiges Zeichen aus dieser Liste“. Dies bedeutet, dass wir die (|
) Wechseloperator weil wir es nicht brauchen.
Wir können den Zeilenanfangsanker auf alle Elemente in der Liste innerhalb der Klammern anwenden ([]
). (Beachten Sie, dass der Anfang des Linienankers außerhalb der Klammern liegt).
Wir geben Folgendes ein, um nach einer Zeile zu suchen, die mit einem großen „N“ oder „W“ beginnt:
grep -E '^[NW]' geeks.txt

Wir werden diese Konzepte auch in den nächsten Befehlen verwenden.
Wir geben Folgendes ein, um nach Personen namens Tom oder Tim zu suchen:
grep -E 'T[oi]m' geeks.txt
Wenn die Einfügemarke (^
) ist das erste Zeichen in den Klammern ([]
) sucht das Suchmuster nach allen Zeichen, die nicht in der Liste erscheinen.
Wir geben beispielsweise Folgendes ein, um nach einem Namen zu suchen, der mit „T“ beginnt, auf „m“ endet und bei dem der mittlere Buchstabe nicht „o“ ist:
grep -E 'T[^o]m' geeks.txt
Wir können eine beliebige Anzahl von Zeichen in die Liste aufnehmen. Wir geben Folgendes ein, um nach Namen zu suchen, die mit „T“ beginnen, auf „m“ enden und einen Vokal in der Mitte enthalten:
grep -E 'T[aeiou]m' geeks.txt

Intervallausdrücke
Sie können Intervallausdrücke verwenden, um anzugeben, wie oft das vorangehende Zeichen oder die Gruppe in der übereinstimmenden Zeichenfolge gefunden werden soll. Sie schließen die Zahl in geschweifte Klammern ein ({}
).
Eine Zahl allein bedeutet speziell diese Zahl, aber wenn Sie ihr ein Komma (,
), bedeutet dies diese Zahl oder mehr. Trennen Sie zwei Zahlen mit einem Komma (1,2
), bedeutet es den Zahlenbereich vom kleinsten bis zum größten.
Wir möchten nach Namen suchen, die mit „T“ beginnen, gefolgt von mindestens einem, jedoch nicht mehr als zwei aufeinanderfolgenden Vokalen und die auf „m“ enden.
Also geben wir diesen Befehl ein:
grep -E 'T[aeiou]{1,2}m' geeks.txt

Dies entspricht „Tim“, „Tom“ und „Team“.
Wenn wir nach der Sequenz „el“ suchen möchten, geben wir Folgendes ein:
grep -E 'el' geeks.txt
Wir fügen dem Suchmuster ein zweites „l“ hinzu, um nur Sequenzen einzuschließen, die doppelte „l“ enthalten:
grep -E 'ell' geeks.txt
Dies entspricht diesem Befehl:
grep -E 'el{2}' geeks.txt
Wenn wir einen Bereich von „mindestens ein und nicht mehr als zwei“ Vorkommen von „l“ angeben, wird dies mit „el“- und „ell“-Sequenzen übereinstimmen.
Dies unterscheidet sich subtil von den Ergebnissen des ersten dieser vier Befehle, bei denen alle Übereinstimmungen für „el“-Sequenzen waren, einschließlich derer innerhalb der „ell“-Sequenzen (und nur ein „l“ ist hervorgehoben).
Wir geben folgendes ein:
grep -E 'el{1,2}' geeks.txt

Um alle Sequenzen von zwei oder mehr Vokalen zu finden, geben wir diesen Befehl ein:
grep -E '[aeiou]{2,}' geeks.txt

Entkommende Charaktere
Nehmen wir an, wir wollen Zeilen finden, in denen ein Punkt (.)
ist das letzte Zeichen. Wir kennen das Dollarzeichen ($
) ist der Zeilenendeanker, also könnten wir Folgendes eingeben:
grep -E '.$' geeks.txt

Wie unten gezeigt, bekommen wir jedoch nicht das, was wir erwartet hatten.

Wie bereits erwähnt, ist der Zeitraum (.
) entspricht jedem einzelnen Zeichen. Da jede Zeile mit einem Zeichen endet, wurde jede Zeile in den Ergebnissen zurückgegeben.
Wie können Sie also verhindern, dass ein Sonderzeichen seine Regex-Funktion ausführt, wenn Sie nur nach diesem tatsächlichen Zeichen suchen möchten? Dazu verwenden Sie einen Backslash (
), um das Zeichen zu maskieren.
Einer der Gründe, warum wir die . verwenden -E
(erweiterte) Optionen liegt daran, dass sie viel weniger Escapes erfordern, wenn Sie die grundlegenden Regexes verwenden.
Wir geben folgendes ein:
grep -e '.$' geeks.txt

Dies entspricht dem tatsächlichen Periodenzeichen (.
) am Ende einer Zeile.
Verankerung und Worte
Wir haben sowohl den Start (^
) und Zeilenende ($
) Anker oben. Sie können jedoch andere Anker verwenden, um an den Grenzen von Wörtern zu arbeiten.
In diesem Zusammenhang ist ein Wort eine Folge von Zeichen, die durch Leerzeichen (der Anfang oder das Ende einer Zeile) begrenzt ist. „psy66oh“ würde also als Wort gelten, obwohl Sie es nicht in einem Wörterbuch finden.
Der Anfang des Wortankers ist (<
); Beachten Sie, dass es nach links zeigt, auf den Anfang des Wortes. Nehmen wir an, ein Name wurde fälschlicherweise in Kleinbuchstaben eingegeben. Wir können die grep verwenden -i
Option, um eine Suche ohne Beachtung der Groß-/Kleinschreibung durchzuführen und Namen zu finden, die mit „h“ beginnen.
Wir geben folgendes ein:
grep -E -i 'h' geeks.txt
Das findet alle Vorkommen von „h“, nicht nur die am Anfang von Wörtern.
grep -E -i '<h' geeks.txt
Dies findet nur diejenigen am Anfang von Wörtern.

Machen wir etwas Ähnliches mit dem Buchstaben „y“; wir wollen nur Fälle sehen, in denen es am Ende eines Wortes steht. Wir geben folgendes ein:
grep -E 'y' geeks.txt
Dadurch werden alle Vorkommen von „y“ gefunden, wo immer es in den Wörtern vorkommt.
Jetzt geben wir Folgendes ein, indem wir das Ende des Wortankers (/>
) (der nach rechts zeigt, oder das Ende des Wortes):
grep -E 'y>' geeks.txt

Der zweite Befehl führt zum gewünschten Ergebnis.
Um ein Suchmuster zu erstellen, das nach einem ganzen Wort sucht, können Sie den Grenzoperator (b
). Wir verwenden den Grenzoperator (B
) an beiden Enden des Suchmusters, um eine Zeichenfolge zu finden, die in einem größeren Wort enthalten sein muss:
grep -E 'bGlennb' geeks.txt
grep -E 'BwayB' geeks.txt

Weitere Zeichenklassen
Sie können Tastenkombinationen verwenden, um die Listen in Zeichenklassen anzugeben. Diese Bereichsindikatoren ersparen Ihnen, jedes Mitglied einer Liste in das Suchmuster einzugeben.
Sie können alles Folgende verwenden:
- AZ: Alle Großbuchstaben von „A“ bis „Z“.
- az: Alle Kleinbuchstaben von „a“ bis „z“.
- 0-9: Alle Ziffern von null bis neun.
- dp: Alle Kleinbuchstaben von „d“ bis „p“. Mit diesen Formatvorlagen im freien Format können Sie Ihren eigenen Bereich definieren.
- 2-7: Alle Zahlen von zwei bis sieben.
Sie können auch beliebig viele Zeichenklassen in einem Suchmuster verwenden. Das folgende Suchmuster entspricht Sequenzen, die mit „J“ beginnen, gefolgt von einem „o“ oder „s“ und dann entweder einem „e“, „h“, „l“ oder „s“:
grep -E 'J[os][ehls]' geeks.txt

In unserem nächsten Befehl verwenden wir das a-z
Bereichsspezifizierer.
Unser Suchbefehl gliedert sich wie folgt auf:
- H: Die Sequenz muss mit „H“ beginnen.
- [a-z]: Das nächste Zeichen kann ein beliebiger Kleinbuchstabe in diesem Bereich sein.
- *: Der Stern steht hier für eine beliebige Anzahl von Kleinbuchstaben.
- Mann: Die Sequenz muss mit „man“ enden.
Wir fassen alles in folgendem Befehl zusammen:
grep -E 'H[a-z]*man' geeks.txt

Nichts ist undurchdringlich
Bei einigen Regexes kann es schnell schwierig werden, visuell zu analysieren. Wenn Leute komplizierte Regexe schreiben, fangen sie normalerweise klein an und fügen immer mehr Abschnitte hinzu, bis es funktioniert. Sie neigen dazu, im Laufe der Zeit an Raffinesse zuzunehmen.
Wenn Sie versuchen, von der endgültigen Version aus rückwärts zu arbeiten, um zu sehen, was sie bewirkt, ist dies eine ganz andere Herausforderung.
Sehen Sie sich zum Beispiel diesen Befehl an:
grep -E '^([0-9]{4}[- ]){3}[0-9]{4}|[0-9]{16}' geeks.txt
Wo würden Sie anfangen, das zu entwirren? Wir beginnen am Anfang und nehmen es Stück für Stück:
- ^: Der Linienanfangsanker. Also muss unsere Sequenz das Erste in einer Zeile sein.
- ([0-9]{4}[- ]): Die Klammern fassen die Suchmusterelemente zu einer Gruppe zusammen. Andere Operationen können auf diese Gruppe als Ganzes angewendet werden (dazu später mehr). Das erste Element ist eine Zeichenklasse, die einen Ziffernbereich von null bis neun enthält
[0-9]
. Unser erstes Zeichen ist also eine Ziffer von null bis neun. Als nächstes haben wir einen Intervallausdruck, der die Zahl vier enthält {4}
. Dies gilt für unser erstes Zeichen, von dem wir wissen, dass es eine Ziffer sein wird. Daher ist der erste Teil des Suchmusters jetzt vierstellig. Es kann entweder ein Leerzeichen oder ein Bindestrich folgen ([- ]
) aus einer anderen Zeichenklasse.
- {3}: Ein Intervallbezeichner mit der Zahl drei folgt unmittelbar auf die Gruppe. Es wird auf die gesamte Gruppe angewendet, daher besteht unser Suchmuster jetzt aus vier Ziffern, gefolgt von einem Leerzeichen oder einem Bindestrich, der dreimal wiederholt wird.
- [0-9]: Als nächstes haben wir eine weitere Zeichenklasse, die einen Ziffernbereich von null bis neun enthält
[0-9]
. Dadurch wird dem Suchmuster ein weiteres Zeichen hinzugefügt, das eine beliebige Ziffer von null bis neun sein kann.
- {4}: Ein anderer Intervallausdruck, der die Zahl Vier enthält, wird auf das vorherige Zeichen angewendet. Dies bedeutet, dass aus einem Zeichen vier Zeichen werden, die alle eine beliebige Zahl von null bis neun sein können.
- |: Der Alternation-Operator sagt uns, dass alles links davon ein vollständiges Suchmuster ist und alles rechts davon ein neues Suchmuster. Dieser Befehl sucht also tatsächlich nach einem von zwei Suchmustern. Die erste besteht aus drei Gruppen von vier Ziffern, gefolgt von einem Leerzeichen oder einem Bindestrich, und dann werden weitere vier Ziffern angeheftet.
- [0-9]: Das zweite Suchmuster beginnt mit einer beliebigen Ziffer von null bis neun.
- {16}: Ein Intervalloperator wird auf das erste Zeichen angewendet und in 16 Zeichen umgewandelt, die alle Ziffern sind.
Unser Suchmuster wird also nach einem der folgenden suchen:
- Vier Gruppen mit vier Ziffern, wobei jede Gruppe durch ein Leerzeichen oder einen Bindestrich (
-
).
- Eine Gruppe von sechzehn Ziffern.
Die Ergebnisse werden angezeigt unter.

Dieses Suchmuster sucht nach gängigen Formen des Schreibens von Kreditkartennummern. Es ist auch vielseitig genug, um mit einem einzigen Befehl verschiedene Stile zu finden.
Lass es langsam angehen
Komplexität ist normalerweise nur eine Menge Einfachheit, die zusammengeschraubt wird. Sobald Sie die grundlegenden Bausteine verstanden haben, können Sie effiziente, leistungsstarke Dienstprogramme erstellen und wertvolle neue Fähigkeiten entwickeln.