Reguläre Ausdrücke auf Kommandozeilen und in Programmiersprachen

(Last Updated On: 23. Januar 2016)

Reguläre Ausdrücke (regular ExpressionS) sind eigentlich eine gute Erfindung. Denn: Sie erlauben das Suchen nach oder Ersetzen von  Zeichenketten abhängig von bestimmten TExtmustern. So könnten Sie beispielsweise in einer Textdatei ganz einfach nach einem GEburtsdatum suchen, indem Sie nach einer Zeichenkette aus zwei Zahlen, einem Punkt, weiteren zwei Zahlen, einem Punkt und abschließend 2 oder auch vier Zahlen suchen. So ein Suchmuster ist nur dank regulärer Ausdrücke möglich. REguläre Ausdrücke sind eine echte PAin in the Ass. Denn: Sie sind nicht überall gleich. Je nachdem, ob Sie reguläre Ausdrücke in dieser (z. B. JavaScript) oder jener (z. B. Perl) Skript- bzw. Programmiersprache nutzen wollen oder auf der Linux-Shell oder Windows Power Shell arbeiten, sind sie immer etwas unterschiedlich. Denn die Implementierung regulärer Ausdrücke ist nicht genormt, die Implementierung hängt also einzig allein vom Bereitsteller der Funktionalität ab.

Dieser Post, der regelmäßig geupdatet wird, soll sammeln, wie man reguläre Ausdrücke auf verschiedenen Kommandozeilen, Skript- und Programmiersprachen verwendet.

Aktuell beinahltet der Post nur Grundlagen, die überall gelten, und spezifische Hinweise für die Linux Shell. Mit der Ziet werde ich noch Hinweise für die Windows PowerShell, Windows cmd und für verschiedene Programmiersprachen hinzufügen.

Reguläre Ausdrücke – Grundlagen

die folgenden Grundlagen funktionieren (Gott sei DAnk) in allen Implementierungen von regulären Ausdrücken. So konnte sich zumindest teilweise eine kleine STandardisierung von regulären Ausdrücken durchsetzen.

^ Zeichenketten beginnen mit

Mit dem Zirkumflex können Sie überall nach Zeichenketten suchen, mit einem bestimmten String beginnen sollen. Sie können beispielsweise sagen, ich möchte in einer datei alle Zeilen haben, die mit einer Raute (#) beginnen. Unter Linux würden Sie dazu das  komamndo grep verwenden

grep ^# <datei>

einige Anwendender grübeln immer bei der Frage: „was ist, wenn ich nach einer Zeichenkette suchen möchte, die mit einem Leerzeichen afange?“. DAfür liefern reguläre Ausdrücke entsprehcende Platzhalter, beispielsweise können Sie das folgendermaßen abfragen.

egrep '^\s' <datei>

Das ganze können Sie noch weiter stricken. Was ist denn jeztt, wenn wir wollen, dass sowohl Zeilen, die mit einem Leerzeicehn beginnen, als auch Zeilen, die mit einer Raute beginnen, ausgegeben werden? Nun, dafür bieten reguläre Ausdrücke den Oder-Operator |, sodass wir folgendermaßen arbeiten könnten.

egrep '^\s|^#' <datei>

Leere Zeilen, die nur einen Carriage Return (also einen Zeilenumbruch) enthalten, findet man mit

grep ^$ <datei>

das Dollar steht hier entsprechend stellvertretend für einen Zeilenumbruch.In der Praxis möchte man jedoch meist genua das Gegenteil, also alle Zeilen außer die LEerzeilen finden, daher verwendet amn in der Praxis häufig

grep -v ^$ <datei>

Sie können auch andere sogenannte non-printing characters auf diese Art und Weise finden. Wenn Sie erst wissen müssen, welches Ziechen für den von Ihnen gesuchten non-printing-character steht, können Sie diesen rausfinden über

cat -vet <datei>

Der non printing character wird dann mit dem Zeichen dargestellt, mit dem er in regular Expressions vertreten wird.

^ außerhalb von [] ist nicht das selbe wie innerhalb von [^]

während ein Zirkumflex außerhalb von eckigen Klammern bedeutet, „suche nach Zeichenketten die mit damit beginnen: “ sagt ein Zirkumflex innerhlab von eckigen klammern „Suche nach allem außer dem, was in den eckigen Klammern steht“. [^a-z] sucht also nach allem, was keine Kleinbuchstaben von a-z hat.

$ Zeilen enden mit

Jetzt da wir wissen, dass das Dollar-Zeichen für einen Zeilenumbruch steht, können wir mit

grep .$ <datei>

sagen, wir wollen alles auswählen, was mit einem Punkt aufhört, wenn danach eine neue Zeile beginnt. Wir können also nach Zeilenenden suchen.

Zeichenketten mit einem einzigen Zeichen einer bestimmten Art an einer bestimmten STelle

Was ist, wenn ich aus einer Datei nun alle Zeilen mit Worten mit c<irgendein Buchstbae>t haben möchte, also z. B. cat, cUt, ctt, cOt usw.?

Hierfür gibt es den Punkt. Unter Linux könntet ihr beispielswiese nach einer derartigen Zeichenkette wieder suchen mit

grep "c.t" <datei>

Was nun aber, wenn ihr beispielsweise wollt, dass zwischen c und t nur Vokale stehen dürfen? Damit würden wir noch Zeichenketten mit cat und cut, aber keine mehr mit ctt, cdt o. Ä. erwischen. In disem Fall könnt ihr eine sogenannte Range an Zeichen, die in die Zeichenkette passen dürfen, angeben.

grep "c[aeiou]t" <datei>

Wenn ihr hingeen wollt, dass alle Buchstaben von A-P an der STelle sein dürfen, womit Zeichenketten wie cat, cpt, cot, ckt, cbt etc. ausgewählt werden würden, könntet ihr angeben:

grep "c[a-p]t" <datei>

Im Moment wählen wir aber nur  Kleinbuchstbaen aus. wEnn wir auch Großbuchstaben auswählen wollen, müssen wir mit dem Oder-Operator (|) arbeiten und sagen

grep "c[a-pA-P]|" <datei>

Damit werden nun auch die Großbuchstaben A-P ausgewählt.

Was ist nun, wenn ihr nach Ziffern in einer Datei suchen wollt? In diesem Fall würden wir sagen

grep "[0-9]" <datei>

Und wenn es statt einstelligen Ziffern nur dreistellige Zahlen sein dürfen (100, 101, 199, 200, 999 etc.), dann schreiben wir

grep "[0-9][0-9][0-9]" <datei>

Statt solcher Ranges kann man auch Klassen angeben

  • [[:alpha:]] ist das selbe wie [a-zA-Z]
  • [[:upper:]] ist das selbe wie [A-Z]
  • [[:lower:]] ist das selbe wie [a-z]
  • [[:digit:]] ist das slebe wie [0-9]
  • [[:alnum:]] ist das selbe wie [0-9a-zA-Z]
  • [[:space:]] wählt alle White Spaces, also bspw. Leerzeichen oder Tabstopps, aus.
  • [[:punct:]] wählt alle Sonderzeichen aus, also !"#$%&'()*+,
    \-./:;<=>?@
    [\\\]^_`{|}~]
  • weitere Klasen findet ihr unter http://www.regular-expressions.info/posixbrackets.html

und statt dieser Klassen kann man man auch Abkürzungen schreiben wie beispielswiese

  • \d  ist das selbe wie [0-9]
  • \w ist das selbe wie [0-9a-zA-Z_] (hier ist also der Unterstrich dabei)
  • \s wählt nicht nur Whitespaces (Leerzeciehn und Tabstopps), sondern auch neue Zeilenumbrüche (\n), Zeilenrücksprungmarkierungen (carriage return,\n) und Seitenumbrüche (\f) aus. Achtung: Das ist NICHT das selbe wie [[:space:]]. [[:space:]] kümmert sich NUR und ausschließlich um Whitespaces, also Leerstellen und Tabstopps, \s kümmert sich AUSSERDEM um non-printing-characters, also um Zeichen, die man bei der Ausgbae des Dokuments nicht sieht.

Wenn diese Abkürzungen (Abbreviations) groß geschrieben werden, sucht man nach Zeichenketten, die nicht diese Zeichenketten enthalten.. /D sucht also nach allen Zeichenketten, die keine Ziffer enthalten. [^0-9]

Quantifiers – nicht zu verwechseln mit Wildcards

Natürlich können Sie nach dreistelligen Zahlen statt mit

[0-9][0-9][0-9]

beispielsweise auch suchen über

[0-9]{3}

Dieses Konzept nennt man quantifizieren, also ein Suchmuster muss mehrfals vorkommen. Diese Quantifizierer kombiniert man am besten entweder mit Ranges, z. B.

[a-zA-z]{10}

Jedoch gibt es quhc Auntifizierer, die ohne Ranges auskommen, beispielswiese

  • ^A+ sucht nach allen Zeichenketten, die mindestens ein großes A, aber auch mehrere davon beinahlten.
  • A? sucht nach Zeichenketten, die entweder gar kein oder wenn dann nur ein einziges großes A enthalten.
  • A* sucht nach Zeichenketten, die entweder gar kein oder beliebig viele große A benhalten.

damit sollte auch klar sein, dass A* oder A? in Regulären Ausdrücken was anderes bedueutet als man es von Wildcards gewohnt ist, die man beispielsweise an anderen Stellen in der Linux Shell oder der Windows Eingabeaufforderung verwenden kann. Denn in der Linux Shell oder in der windows Eingabeaufforderung würde A* bedeueten:

„Suche nach allen Dateien, die nach einem großen A entweder gar nichts mehr oder beliebig viele Zeichen haben“

Während also A* bei regulären Ausdrücken neben einer Datei  bzw. Zeichenkette namens A auch eine Datei oder Zeichenkette namens B oder C auswählen würde, würde man bei der Windows eingabeaufforderung damit neben A nicht mehr B oder C, sondern nur noch AA,  AB, AC usw. auswählen, da diese den Asterisk (*) als Wildcard interpretiert.

A? wählt bei regulären Ausdrücken ebenfalls A, B und C aus, während die Linux Shell oder Windows Eingabeaufforderung nur A, AA, AB, usw. auswählt. Diesen Unterschied zu kennen ist essentiell, denn die Linux Binary grep versteht ein A* im Sinne des regulären Ausdrucks, während beispielsweise das Kommando ls -la A* im Sinne einer Wildcard interpretiert. Diese Feinheit bringt viele administratoren zur täglichen Verzweiflung, wenn Sie versuchen, im Linux-Kommando grep den Stern (*) und das Fragezeichen (?) wie eine Wildcard zu verwenden.

Regular Expressions in der Linux Shell

Welche reguläre Ausdrücke unterstützt werden, ist in der Linux Shell leider immer sehr abhängig von der binary, die Sie verwenden wollen. Beispielswiese unterstützt das kommando grep keinen Oder-Operator, sodass Sie bei einem regulären Ausdruck wie beispielsweise

grep '^\s|^#' <datei>

ins Leere schauen würden. Verwenden Sie hingegen stattdessen egrep, funktioniert es wieder. Das führt leider bei vielen unerfahrenen Linux-Usern häufig zu Frustration.

Wie bereits wieter oben bei den Grundlagen im Kapitel Quantifiers erwähnt, gibt es Binaries, die einen Ausdruck wie A* als Quantifizierer im Sinne eines regulären Ausdrucks verstehen (z. B: egrep), und andere Binarys diesen als Wildcard interpretieren (z. B. ls).

Andreas Loibl ist SAP-Berater, Ethical Hacker und Online Marketing Manager und schreibt auf seinem Blog DaFRK Blog über verschiedene Themen in den Sektoren Projektmanagement, Informationstechnik, Persönlichkeitsentwicklung, Finanzen und Zeitmanagement.

DaFRK

Andreas Loibl ist SAP-Berater, Ethical Hacker und Online Marketing Manager und schreibt auf seinem Blog DaFRK Blog über verschiedene Themen in den Sektoren Projektmanagement, Informationstechnik, Persönlichkeitsentwicklung, Finanzen und Zeitmanagement.

Das könnte Dich auch interessieren …

1 Antwort

  1. 23. Januar 2016

    […] Ergänzung, um die regulären Ausdrücke aus diesem kapitel zu verstehen, solltet ihr meinen Post über reguläre Ausdrücke lesen bzw. darin als Referenz […]

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.