Wann du zu Regex greifst
Reguläre Ausdrücke sind eine kleine Sprache zum Beschreiben von Textmustern. Sie sind mächtig und leicht zu überstrapazieren.
Bevor du zu re greifst, frag, ob schlichte String-Methoden reichen. .split(), .replace(), .startswith(), "target" in text — die sind schneller, lesbarer und weniger fehleranfällig als die entsprechenden Regexes. Heb dir Regex für das auf, wenn das gewünschte Muster wirklich strukturiert ist, aber zu flexibel für feste String-Operationen: E-Mail-Adressen, Telefonnummern, Logzeilen mit bekannter Form, HTML- oder Markdown-Schnipsel, jede „finde diese Art Ding“-Suche.
Das Grundvokabular
Ein Regex-Muster ist ein String, der beschreibt, wonach du suchst. Ein paar Bausteine:
.— ein beliebiges einzelnes Zeichen\d— eine beliebige Ziffer (0–9)\w— ein beliebiges „Wort“-Zeichen (Buchstabe, Ziffer, Unterstrich)\s— ein beliebiges Leerzeichen^— Stringanfang$— Stringende[abc]— eines von a, b oder c[^abc]— irgendein Zeichen außer a, b, ca|b— a oder b*— null oder mehr vom Vorherigen+— eins oder mehr?— null oder eins{3}— genau 3{2,5}— zwischen 2 und 5( ... )— Gruppe (fängt den Treffer darin ein)
Das reicht für die meisten realen Regexes.
Die Schlüsselfunktionen
re.search(pattern, text) findet den ersten Treffer irgendwo im String. Liefert ein Match-Objekt oder None:
Nutz immer einen Raw-String (r"...") für Regex-Muster. Sonst versucht Python, die Backslashes als String-Escapes zu interpretieren, und du bekommst ein anderes Muster als getippt.
re.match(pattern, text) ist wie search, matcht aber nur am Anfang:
Meistens willst du search.
re.findall(pattern, text) liefert alle überlappungsfreien Treffer als Liste:
Beachte: findall liefert Strings, keine Match-Objekte. Hat dein Muster eine Gruppe, bekommst du den Gruppeninhalt zurück. Mit mehreren Gruppen bekommst du eine Liste von Tupeln.
Gruppen einfangen
Klammern in einem Muster fangen ein, was darin gematcht wurde:
Benannte Gruppen sind meistens klarer:
Hat die Regex mehr als eine Gruppe, macht Benennen den Extraktionscode viel leichter verfolgbar.
Ersetzen mit re.sub
re.sub(pattern, replacement, text) ersetzt jeden Treffer:
Das entfernt alles, was keine Ziffer ist. Die Ersetzung kann eingefangene Gruppen mit \1, \2 usw. referenzieren — oder in Raw-Strings ist \g<1> klarer:
Du kannst auch eine Funktion als Ersetzung übergeben. Das ist nützlich für Transformationen, die kein simpler Tausch sind:
Muster zur Wiederverwendung kompilieren
Nutzt du dasselbe Muster oft — besonders in einer Schleife —, kompilier es einmal:
Kompilierte Muster bieten dieselben Methoden — search, match, findall, sub — ohne das Muster als erstes Argument. Etwas effizienter, oft lesbarer.
Flags
Gebräuchliche Modifikatoren, als flags=-Argument oder per OR verknüpft:
re.IGNORECASE(re.I) — case-insensitive Matching.re.MULTILINE(re.M) —^und$matchen an jeder Zeile, nicht nur an den String-Rändern.re.DOTALL(re.S) —.matcht auch Zeilenumbrüche (standardmäßig nicht).re.VERBOSE(re.X) — erlaubt Leerzeichen und#-Kommentare im Muster für Lesbarkeit.
re.VERBOSE ist besonders nützlich für komplexe Muster:
Mehrzeilige, kommentierte Regexes sind viel leichter zu pflegen als undurchsichtige Einzeiler.
Gierig vs. Faul
Quantifier (*, +, ?, {n,}) sind standardmäßig gierig — sie matchen, so viel sie können. Ein angefügtes ? macht sie faul:
Die gierige Version fängt den ganzen Teilstring von <b> bis </i> ein — wahrscheinlich nicht das, was du wolltest. Das faule .+? stoppt am ersten >.
(Nebenbei: parse HTML in Produktion nicht mit Regex. Nimm html.parser oder BeautifulSoup. Das Beispiel oben soll nur Gier illustrieren.)
Ein realistisches Beispiel
Zeilen aus einem einfachen Log-Format parsen:
Viel Power in wenigen Zeilen.
Ein paar Gewohnheiten
- Nutz immer Raw-Strings für Muster.
- Beginn mit dem einfachsten funktionierenden Muster; zieh es später enger.
- Nutz benannte Gruppen, sobald du mehr als eine hast.
- Kompilier Muster, die du wiederverwendest.
- Regex ist langsamer als schlichte String-Methoden. Reicht
.split(), nimm.split().
Als Nächstes: Fehler und Debugging
Damit schließt die Tour durch echte Daten — Dateien, JSON, CSV, HTTP, Daten und Regex. In einem echten Programm trifft früher oder später jedes auf einen Fehler, und Python-Tracebacks gut zu lesen ist die größte einzelne Debugging-Fertigkeit, die du dir aneignen kannst. Das letzte Kapitel behandelt Ausnahmen und die konkreten Fehler, denen du am häufigsten begegnest.
Häufig gestellte Fragen
Was ist Regex in Python?
Ein regulärer Ausdruck (Regex) ist eine kleine Sprache, um Muster in Text zu beschreiben. Pythons re-Modul erlaubt dir, nach Mustern zu suchen, Teile zu extrahieren und Treffer zu ersetzen. Für einfache String-Operationen ist es übertrieben — nimm zuerst String-Methoden wie .split() oder .replace() —, aber für strukturierte Mustererkennung unschlagbar.
Was ist der Unterschied zwischen re.match und re.search?
re.match matcht nur am Anfang des Strings. re.search scannt den ganzen String und findet den ersten Treffer irgendwo. Im Zweifel: search — das entspricht der menschlichen Intuition besser.
Soll ich für Regex-Muster immer Raw-Strings nutzen?
Ja. Regex-Muster enthalten oft Backslashes (\d, \s, \b), die Python-Strings als Escape-Sequenzen interpretieren. Ein vorangestelltes r — r'\d+' — sagt Python, den String wörtlich zu nehmen, was die Regex selbst lesbar hält.