- 1 Section
- 10 Lessons
- unbegrenzt
- Reguläre Ausdrücke & Textverarbeitung10
- 1.1Was sind Reguläre Ausdrücke?
- 1.2Grundzeichen: Literale, Zeichenklassen, Quantoren
- 1.3Anker, Gruppen und Alternation
- 1.4Gierige vs. faule Quantoren
- 1.5Regex in Python: re-Modul
- 1.6Regex in JavaScript
- 1.7grep, sed, awk – Regex auf der Kommandozeile
- 1.8Regex für Validierung: E-Mail, IP, PLZ, Datum
- 1.9Regex in Datenbanken: LIKE, REGEXP
- 1.10Aufgaben Reguläre Ausdrücke
Anker, Gruppen und Alternation
Mit den Grundzeichen aus L2 kannst du schon viele Muster bauen – aber dir fehlen drei wichtige Konzepte: Anker (Positionen statt Zeichen), Gruppen (Teile zusammenfassen und einfangen), Alternation (Oder-Verknüpfungen). Ohne diese drei sind Regex eingeschränkt – mit ihnen wirst du fast jedes Pattern formulieren können.
Diese Lektion ist konzeptuell etwas anspruchsvoller als L2, lohnt sich aber: Anker verhindern dass dein PLZ-Pattern auch in Telefonnummern matched. Gruppen ermöglichen erst das Extrahieren von Teilen (Vor- und Nachname getrennt aus „Anna Müller"). Alternation macht Patterns flexibler („akzeptiere ja, yes oder ok").
1) Anker: Position statt Zeichen
Bisher matched jedes Element ein Zeichen. Anker sind anders: sie matchen eine Position im Text, ohne ein Zeichen zu konsumieren. Sie sind „Zero-Width Assertions". Klingt abstrakt – wird klar wenn du die Auswirkungen siehst.
Die wichtigsten Anker:
^– Zeilenanfang. Matched die Position vor dem ersten Zeichen einer Zeile.$– Zeilenende. Matched die Position nach dem letzten Zeichen.\b– Wortgrenze. Position zwischen Wort- und Nicht-Wort-Zeichen.\B– Nicht-Wortgrenze. Das Gegenteil.\A– Anfang des ganzen Strings (nicht nur Zeile)\Zoder\z– Ende des ganzen Strings
Praktischer Effekt: \d{5} findet auch in „12345678" die ersten 5 Ziffern – mitten in einer längeren Zahl. ^\d{5}$ matched nur dann wenn der ganze String aus genau 5 Ziffern besteht. Das ist der Unterschied zwischen „Suche" und „Validierung". Genau das brauchst du wenn du eine komplette Eingabe prüfen willst – siehe L8 Validierung.
2) Anker-Diagramm
Schauen wir uns die Positionen visuell an. Im folgenden Text sind alle Anker-Positionen markiert: grün für Zeilenanfang/Stringanfang, rot für Zeilenende, gelb für Wortgrenzen. Klick die Markierungen für Details:
\b sind die nützlichsten Anker im Alltag. \bcat\b findet das Wort „cat" – aber nicht in „category" oder „concatenation". Ohne \b würde es überall matchen. Die Zero-Width-Eigenschaft heißt: der Anker verbraucht kein Zeichen – nach dem Match steht die Engine an derselben Position. Das ist wichtig wenn du mehrere Anker hintereinander setzt (^\b\w+\b$ – „ein Wort von Anfang bis Ende").3) Praxis-Beispiele für Anker
Wann brauchst du welchen Anker? Hier die wichtigsten Fälle:
| Aufgabe | Pattern | Anker-Logik |
|---|---|---|
| 5-stellige PLZ validieren | ^\d{5}$ | ^ + $: ganze Eingabe = 5 Ziffern |
| Zeilen die mit ERROR beginnen | ^ERROR | ^: nur am Zeilenanfang |
| Zeilen die mit .log enden | \.log$ | $: am Zeilenende |
| Ganze Wörter „cat" | \bcat\b | \b: nicht in „category" |
| Nur Wort-Wörter | \b\w+\b | Wort-Grenzen rahmen das Wort |
| Inhalt einer Zeile | ^.+$ | Vom Anfang bis Ende |
Wichtig bei mehrzeiligem Text: standardmäßig matchen ^ und $ nur am String-Anfang/-Ende. Mit dem Flag m (multiline) matchen sie an jedem Zeilenanfang/-ende. Sehr nützlich bei Log-Files mit vielen Zeilen.
4) Gruppen: Zusammenfassen und Einfangen
Mit runden Klammern (...) fasst du mehrere Elemente zu einer Gruppe zusammen. Zwei Hauptanwendungen:
1. Gruppe als Einheit für Quantoren. Bei (ab)+ wird die ganze Gruppe „ab" wiederholt – matched „ab", „abab", „ababab". Ohne Klammern würde nur das letzte Zeichen wiederholt. Beispiel: IP-Adresse mit 4 Oktetten:
Die Gruppe (\.\d{1,3}) = „Punkt gefolgt von 1-3 Ziffern" wird dreimal wiederholt. Plus die erste Ziffernfolge davor = 4 Oktetten zusammen. Eleganter als \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.
2. Gruppen als Capturing Groups: Das ist das echte Highlight. Jede Gruppe speichert ihren Match ab – du kannst später darauf zugreifen. Das brauchst du beim Extrahieren:
Damit holst du einzelne Teile aus dem Match. Bei einer Datums-Extraktion bekommst du sofort Tag, Monat, Jahr getrennt. Bei (\w+)@(\w+\.\w+) bekommst du den lokalen Teil und die Domain separat. Genau das brauchst du bei der Datenverarbeitung. In L5 (Python) und L6 (JavaScript) zeigen wir wie du auf die Gruppen zugreifst.
5) Interaktiver Gruppen-Inspector
Spiel selbst mit Gruppen. Tippe ein Pattern mit Klammern und sieh wie jede Gruppe einzeln im Text gehighlightet wird – jede Gruppe in einer anderen Farbe:
(\d+)/(\d+) für Brüche, (\w+)@(\w+\.\w+) für E-Mails (Username + Domain getrennt), (https?)://(\S+) für URLs (Schema + Rest). Bei Replace-Operationen referenzierst du Gruppen mit $1, $2 usw. – damit kannst du Texte umstrukturieren: (\d{2})\.(\d{2})\.(\d{4}) ersetzen durch $3-$2-$1 macht aus „17.05.2026" das ISO-Format „2026-05-17". Sehr mächtig!6) Capturing vs. Non-Capturing Groups
Manchmal willst du eine Gruppe nur für den Quantor – aber nicht den Inhalt einfangen (das spart Speicher und macht den Code lesbarer). Dafür gibt es Non-Capturing Groups mit der Syntax (?:...):
Wann sinnvoll? Bei komplexen Patterns mit vielen Gruppen, von denen du nur einige brauchst. Beispiel:
Im zweiten Fall ist die www.-Klammer non-capturing – du kümmerst dich nicht darum ob „www." dabei war, aber das Pattern bleibt korrekt.
7) Named Groups
Bei vielen Gruppen verlierst du den Überblick mit $1, $2, ... Lösung: Named Groups. Du gibst der Gruppe einen Namen, greifst per Name darauf zu:
Syntax: (?<name>...). In Python ist es (?P<name>...) mit P, in JavaScript ohne P. In Java und PHP geht es ähnlich.
Vorteil: Code wird viel lesbarer. Statt match[3] schreibst du match.groups.year. Bei späteren Pattern-Änderungen ändert sich nichts am Zugriffs-Code.
8) Alternation: das Oder
Mit dem Pipe-Zeichen | formulierst du Alternativen: „matched A oder B". Beispiele:
ja|nein– matched „ja" oder „nein"cat|dog|bird– matched eines der drei Wörterhttps?|ftp– matched „http", „https" oder „ftp"red|blue|green– Farben
Achtung beim Scope: Pipe wirkt auf den gesamten Pattern-Bereich. cat|dog house matched „cat" ODER „dog house" – nicht „cat house" ODER „dog house". Wenn du die Wahl auf einen Teil beschränken willst: Gruppe um die Alternation:
dog house ✓
cat house ✗
dog house ✓
WARN: ... ✓
INFO: ... ✗
February ✓
March ✓
April ✗
jan(uary)?|feb(ruary)? – die Endungen optional.9) Backreferences: Match wiederverwenden
Ein fortgeschrittenes Feature: Backreferences. Du kannst innerhalb desselben Patterns auf einen früheren Group-Match zurückgreifen mit \1, \2 usw. Damit findest du Wiederholungen:
Im ersten Pattern ist (\w+) die erste Gruppe – sie merkt sich ein Wort. Dann muss \1 dasselbe Wort nochmal matchen. Findet „der der" aber nicht „der das". Klassiker: doppelte Wörter in Texten finden – häufige Tipp-Fehler.
In Replace-Strings sind Backreferences anders: $1 oder \1 abhängig von der Sprache. Sehr mächtig zum Umordnen: (\w+),(\w+) ersetzt durch $2 $1 macht aus „Müller,Anna" das Format „Anna Müller".
10) Lookaheads und Lookbehinds
Die königliche Klasse: Lookarounds. Sie matchen eine Position, prüfen aber ob davor/danach ein bestimmtes Muster steht – ohne es zu konsumieren. Vier Varianten:
X(?=Y)– Positive Lookahead: X matched nur wenn Y folgtX(?!Y)– Negative Lookahead: X matched nur wenn Y NICHT folgt(?<=Y)X– Positive Lookbehind: X matched nur wenn Y davorsteht(?<!Y)X– Negative Lookbehind: X matched nur wenn Y NICHT davorsteht
Beispiel: alle Zahlen finden die nicht von einem $-Zeichen vorgestellt werden:
Sehr mächtig für selektive Suche. Lookarounds sind Zero-Width wie Anker – sie verbrauchen kein Zeichen, sie schauen nur. Nicht alle Sprachen unterstützen das gleich gut – Lookbehind ist in JavaScript erst seit ES2018 dabei, in Python mit Einschränkung (fixe Länge).
11) Klammern-Übersicht
Zur Verwirrung der Anfänger: es gibt vier verschiedene Klammer-Typen. Halt sie auseinander:
| Klammer | Bedeutung |
|---|---|
(...) | Capturing Group (Standard-Gruppe mit Speicher) |
(?:...) | Non-Capturing Group (nur Gruppierung, kein Speicher) |
(?<name>...) | Named Group (mit Namen statt Nummer) |
(?=...) | Positive Lookahead |
(?!...) | Negative Lookahead |
(?<=...) | Positive Lookbehind |
(?<!...) | Negative Lookbehind |
[...] | Zeichenklasse (Auswahl-Menge, kein Gruppen-Konzept!) |
{n,m} | Quantor (Wiederholungs-Bereich) |
Wichtig: (abc) und [abc] sind völlig verschieden. (abc) = exakt die Folge „abc" als Gruppe. [abc] = ein Zeichen, das a, b oder c ist.
12) Zusammensetzen: ein realistisches Beispiel
Bauen wir ein Pattern zum Extrahieren von Telefonnummern im deutschen Format. Es soll matchen: +49 30 12345678, 030/12345678, 030-1234 5678. Schrittweise:
- Ländercode optional:
(\+49)?– die+ist Metazeichen, escapen. - Trennzeichen zwischen Teilen:
[\s/-]?– Space, Slash oder Bindestrich, optional. - Vorwahl 2-5 Ziffern:
\d{2,5} - Trennzeichen wieder:
[\s/-]? - Hauptnummer 6-10 Ziffern (mit optionalem Space):
\d{3,5}[\s-]?\d{3,5} - Anker um das Ganze bei strenger Validierung:
^...$
Zusammengesetzt:
Das matched die obigen Varianten. Komplex – aber genauso baust du jedes praktische Pattern: Stück für Stück, jeden Teil einzeln testen, dann zusammenstecken. Mehr solche Beispiele in L8 Validierung.
Zusammenfassung
Drei mächtige Konzepte: Anker matchen Positionen, kein Zeichen (^ Anfang, $ Ende, \b Wortgrenze) – essenziell für Validierung. Gruppen mit (...) capturen Match-Teile für späteren Zugriff; (?:...) nur gruppieren ohne capturen; (?<name>...) mit Namen. Backreferences \1 oder $1 referenzieren frühere Matches – findet doppelte Wörter, Tag-Paare. Alternation | für Oder, mit Klammern den Scope eingrenzen. Lookarounds (?=...)/(?!...)/(?<=...)/(?<!...) prüfen Umgebung ohne zu konsumieren – z.B. für mehrere unabhängige Bedingungen.
