Geschrieben von

Reguläre Ausdrücke (Regex)

WebDev

Mit regulären Ausdrücken (Regular Expression oder Regex) kann man ein Suchmuster für Zeichenketten definieren. So lassen sich Strings gezielt prüfen und bearbeiten. Vor allem in der Webanalyse und in JavaScript leisten reguläre Ausdrücke hilfreiche Arbeit.

Regex in JavaScript

In JavaScript gibt es verschiedene Arten reguläre Ausdrücke zu verwenden:

  • test-Methode
  • match-Methode

Die test-Methode nimmt das Regex entgegen und wendet es auf einem String an. Zurückgegeben wird entweder true oder false (je nachdem ob das Muster übereinstimmt oder nicht). Beispiel:

let testString = "Das ist ein Test.";
let testRegex = /Test/;
testRegex.test(testString);

Hier gibt die test-Methode ein true zurück. Grund: “Test” kommt im String “Das ist ein Test.” genau so vor. Neben der test- gibt es noch die match-Methode. Großer Unterschied zwischen beiden ist, dass match die Übereinstimmung auch extrahiert:

let testString = "Das ist ein Test.";
let testRegex = /Test/;
testString.match(testRegex);

Zurückgegeben wird [“Test”]. Wie man sehen kann wird match genau gegenteilig im Vergleich zur test-Methode geschrieben:

'string'.match(/regex/);
/regex/.test('string');

Flags, Quantoren und Co.

Case Sensitive

Bleiben wir bei unserem String “Das ist ein Test.”. Wäre unsere Regex-Variable “testRegex” mit dem Ausdruck /test/ versehen, dann würde das Ergebnis ein false zurück geben, da ein regulärer Ausdruck Case Sensitive ist. Um das aufzuheben, wird mit einem sogenannten Flag gearbeitet. Das passende Flag für unseren Zweck heißt “i”. Dieses wird einfach am Regex angehangen:

let testString = "Das ist ein Test.";
let testRegex = /test/i;
testRegex.test(testString);

In diesem Fall gäbe es ein Matching für “Test” und “test”, aber auch für “teST” oder “tEsT” und so weiter.

Oder

Im Regex muss man aber nicht nur nach einem bestimmten Muster suchen, es lässt sich auch eine Oder-Verknüpfung integrieren. Hier ein Beispiel:

let testString = "Das ist ein Test.";
let testRegex = /Das|Test/;
testRegex.test(testString);

Mit dem Operator | lässt sich also eine Oder-Verknüpfung herstellen.

Globale Suche

Bisher konnten wir das gesuchte Muster nur einmal exstrahieren:

let testString = "Test, Test, Test";
let testRegex = /Test/;
testRegex.test(testString);

Die match-Methode würde hier [“Test”] zurückgeben. Möchten wir, dass die Suche weitergeht können wir mit dem g-Flag arbeiten:

let testString = "Test, Test, Test";
let testRegex = /Test/g;
testRegex.test(testString);

Hier gibt die match-Methode [“Test”, “Test”, “Test”] zurück.

Wildcard

Um nach einem beliebiegen Zeichen im Muster zu suchen, kann das Wildcard-Zeichen “.” eingesetzt werden:

let ersterString = "Das ist ein Test.";
let zweiterString = "Das ist ein Fest.";
let testRegex = /.est/;
testRegex.test(ersterString);
testRegex.test(zweiterString);

Da der Punkt als Platzhalter für ein beliebieges Zeichen steht, geben beide test-Methoden ein true zurück.

Zeichenauswahl

Mit eckigen Klammern [] lassen sich eine Gruppe von Zeichen definieren, nach denen man suchen möchte. Hier ein Beispiel:

let kaiStr = "Kai";
let maiStr = "Mai";
let haiStr = "Hai";
let daiStr = "Dai";
let kmhRegex = /[KMH]ai/;
kaiStr.match(kmhRegex);
maiStr.match(kmhRegex);
haiStr.match(kmhRegex);
daiStr.match(kmhRegex);

Hier hätten wir als Ergebnis [“Kai”], [“Mai”], [“Hai”] und null. Mit der Zeichenklasse [KMH] lassen wir uns die Strings zurückgeben, die den Zeichen K, M oder H vor “ai” entsprechen.

Bereich definieren

Im vorherigen Beispiel haben wir nach 3 Buchstaben gesucht. Was wenn aber nach einem größeren Bereich gesucht werden soll? Statt jeden einzelnen Buchstaben aus dem Alphabet abzutippen, kann ein Bereich definiert werden:

let katString = "Katze";
let matString = "Matze";
let satString = "Satze";
let myRegex = /[K-S]atze/;
katString.match(myRegex);
matString.match(myRegex);
satString.match(myRegex);

Das gleiche Prinzip funktioniert auch mit Zahlen. [0-9] würde z.B. alle Zahlen zwischen 0 und 9 einschließen. Auch lässt es sich kombinieren:

let userName = "Max1234324";
let myRegex = /[a-z0-9]/ig;
userName.match(myRegex);

Negierte Zeichenauswahl

Mit dem Zirkumflex-Zeichen (^) innerhalb eckigen Klammern negiert man die darauffolgende Zeichenauswahl. /[^aeiou]/gi würde mit allen Zeichen, die nicht ein Vokal sind, übereinstimmen. Beispiel:

let myStr = "3 blind mice.";
let myRegex = /[^aeiou0-9]/gi;
let result = myStr.match(myRegex);

Das Ergebnis lautet dann [” “, “b”, “l”, “n”, “d”, ” “, “m”, “c”, “.”].

Plus-Zeichen

Um zu prüfen, ob ein Zeichen einmal oder mehrmals hintereinander vorkommt, kann das Plus-Zeichen benutzt werden. Beispiele:

  • /a+/g würde bei “abc” passen und [“a”] zurückgeben. Auch bei “aabc” würde es passen und [“aa”] zurückgeben.
  • Bei “abab” würde es jedoch [“a”, “a”] zurückgeben, da hier zwischen den a ein b ist.

Stern-Zeichen

Der Stern ist ähnlich wie das Plus-Zeichen, nur das beim Stern geprüft wird, ob ein Zeichen keinmal oder mehrmals hintereinander vorkommt. Beispiel:

let str1 = "haaaaaaallo";
let str2 = "huhu";
let str3 = "ola";
let myRegex = /ha*/;
str1.match(myRegex);
str2.match(myRegex);
str3.match(myRegex);

Die Rückgabe wäre nun [“haaaaaaa”], [“h”] und null.

“Gierige” und “genügsame” Übereinstimmung

Reguläre Ausdrücke sind standardmäßig “gierig” (greedy). Das bedeutet, dass immer eine längstmögliche Übereinstimmung, die dem Regex-Muster entspricht, gefunden und zurückgegeben wird. Die Alternative dazu ist das Lazy-Matching, welches den kleinstmöglichen Teil des Strings findet.

Gehen wir vom Regex /f[a-z]*g/ aus und wenden es auf “flugzeug” an. Das Regex sucht nach einem String, der mit f beginnt, keinmal oder mehrmals Buchstaben zwischen a und z besitzt sowie mit g endet. Ergebnis wäre [“flugzeug”]. Das Regex ist also gierig und findet die längstmögliche Übereinstimmung.

Um die kleinstmögliche Übereinstimmung zu finden (also Lazy-Matching) kann das Fragezeichen benutzt werden: /f[a-z]*?g/. Das würde dann [“flug”] zurückgeben, das es “faul” ist und schon nach der kleinstmöglichen Übereinstimmung aufhört.

Übersicht wichtiger Regex

RegexErklärung
.Beliebiges Zeichen
*Keinmal oder beliebig oft
?Vorangegangenes Zeichen soll 0-mal oder 1-mal vorkommen
+Vorangegangenes Zeichen muss min. 1-mal vorkommen
|Oder
[abc]Findet a, b oder c
[1-9]Findet alles zwischen 1 und 9
()Gruppierung
{}Definiert wie häufig ein Suchmuster max. vorkommen darf. Bei hal{1,3} darf das vorangegangene “l” min. 1-mal, aber max. 3-mal vorkommen. “hal”, “hall” und “halll” würden daher passen.
\Nachfolgendes Regex-Zeichen wird als normales Zeichen interpretiert
^Muss mit nachfolgenden Zeichen anfangen
$Muss mit vorherigen Zeichen enden
\dStimmt mit einer beliebigen Zahl zwischen 0 und 9 überein.
\DStimmt nicht mit Zahlen überein, also das Gegenteil von “\d”.
\wStimmt mit allen Zahlen zwischen 0 und 9, allen Buchstaben von a bis z sowie A bis Z und dem Underscore “_” überein.
\WGegenteil von “\w”.
\sStimmt mit allen Leerzeichen überein (Leertaste, Tab und Enter).