Reguläre Ausdrücke zum Ansehen
·
Kursüberblick
1
Die verschwundene Zahlung: Text wörtlich finden
2
Der Fluchtwagen: Zeichenklassen
3
Das zerrissene Telefonbuch: Quantoren
4
Die falschen Anmeldungen: Anker und Validierung
5
Daten in jedem Format: Gruppen und Alternativen
6
Der Zugriff um 3 Uhr nachts: benannte Gruppen und Match-Objekte
7
Die Nacht vor der Story: Ersetzen und Aufteilen
8
Die Herausforderung des Backtrackers: gierig, genügsam, possessiv
9
Die Regeln des Tresors: Lookaround
10
Gleiche Masche: Rückverweise und Bedingungen
11
Der unlesbare Regex: Flags und Kompilieren
12
Die Enttarnung des Backtrackers: Rückblick und ein Tokenizer
CASE-003
Grep & Co. Datendetektei
Fallakte
Auftraggeber
Die Floristin vom Blumenladen „Wildblume“ in der Gasse
Beweismittel
Die per OCR eingelesene Liste aus dem verregneten, zerrissenen Telefonbuch der Stammkundschaft. Jede Nummer hat andere Trennzeichen, und zwischendrin stehen Zahlen, die da nicht hingehören.
Zum Abschluss des Falls
Sammle alle Telefonnummern und Postleitzahlen aus der Liste.
Als du morgens ankommst, hat die Chefin das Nummernschild-Muster von gestern auf dem Bildschirm. „Statt viermal \d zu schreiben, kann man auch einfach ‚viermal‘ hinschreiben. Das lernst du heute.“ In dem Moment geht die Tür auf, und die Floristin aus dem Blumenladen in der Gasse kommt mit einem Packen nasser Blätter herein. „Das Telefonbuch meiner Stammkunden ist im Regen völlig aufgeweicht. Ich hab es eingescannt und in Text umwandeln lassen, aber das ist ein einziges Chaos.“
So sieht die per OCR gelesene Liste aus. Jede Nummer hat ein anderes Trennzeichen, und mit der letzten Zeile stimmt irgendwas nicht.
kim 010-0000-1234 04542
lee 010 0000 9876 04545
park 02-0000-5678 04538
choi 010.0000.4321 04539
yoon 1234-5678-9012Die Syntax, mit der du festlegst, wie oft etwas vorkommt, heißt Quantor. Heute bringst du mit Quantoren diese Liste in Ordnung.
Ein Quantor legt fest, wie oft der eine Baustein direkt davor wiederholt wird. \d{4} ist dasselbe wie \d\d\d\d. Kürzen wir damit das Nummernschild-Muster aus Lektion 2.
re.findall(r"\d{2}[가-힣]\d{4}", "12가3457 123가4567") # ['12가3457', '23가4567']Kürzer ist es, aber da ist ein Problem. Die neuen Nummernschilder, die es seit 2019 gibt, haben vorn drei Ziffern. Bei 123가4567 wurde die vordere 1 weggeworfen, und nur 23가4567 kam heraus.
{m,n} heißt mindestens m- und höchstens n-mal. Ändere den vorderen Teil in \d{2,3}, dann werden zwei- und dreistellige Anfänge akzeptiert.
re.findall(r"\d{2,3}[가-힣]\d{4}", "12가3457 123가4567") # ['12가3457', '123가4567']{2,3} keine Leerzeichen vor oder nach das Komma. Mit Leerzeichen ist es kein Quantor mehr (siehe Dots Tipp unten).\d{5}.Beweislabor
re.search(r"", text)
Rückgabewert
Bei {m,n} darfst du eine Seite leer lassen.
{m,} : mindestens m-mal, nach oben offen{,n} : null- bis n-mal. Weil auch null erlaubt ist, passt es auch auf eine Stelle ganz ohne Zeichenre.findall(r"a{2,}", "a aa aaaa") # ['aa', 'aaaa']
re.findall(r"\d{3,}", "1 22 333 4444") # ['333', '4444']
re.findall(r"\d{,2}", "123") # ['12', '3', '']Das '' am Ende des letzten Ergebnisses ist ein Treffer ganz am Ende des Strings, an einer Stelle mit null Ziffern. Solche leeren Treffer schauen wir uns in 3-6 genauer an.
Sieht eine { nicht wie ein Quantor aus, wird sie als normales Zeichen behandelt. a{x} sucht die vier Zeichen a, {, x und }.
re.findall(r"a{x}", "a{x} ax") # ['a{x}']
re.findall(r"a{2, 3}", "aa a{2, 3}") # ['a{2, 3}']Dots Tipp
Ich hab mal a{2, 3} geschrieben, mit einem Leerzeichen nach dem Komma. Kein Fehler, nichts, es hat einfach still und leise was völlig anderes gesucht. Was nicht wie ein Quantor aussieht, gilt eben als normaler Text. Kein Fehler heißt nicht, dass das Muster stimmt. In geschweifte Klammern gehören nur Ziffern und ein Komma.
Die gebräuchlichsten Anzahlen haben einen Namen aus nur einem Zeichen.
| Quantor | Bedeutung | Gleichwertig |
|---|---|---|
* | null- oder mehrmals | {0,} |
+ | ein- oder mehrmals | {1,} |
? | null- oder einmal (darf da sein, muss aber nicht) | {0,1} |
re.findall(r"ab*", "a ab abbb") # ['a', 'ab', 'abbb']
re.findall(r"ab+", "a ab abbb") # ['ab', 'abbb']
re.findall(r"ab?", "a ab abbb") # ['a', 'ab', 'ab']
re.findall(r"colou?r", "color colour colouur") # ['color', 'colour']? passt perfekt für „ein Zeichen, das da sein darf, aber nicht muss“. Bei den Handynummern in der Liste ist das Trennzeichen mal ein Bindestrich, mal ein Leerzeichen, mal ein Punkt. Schreibst du für das Trennzeichen [-. ]?, darf eins der drei dastehen oder auch gar keins.
re.findall(r"010[-. ]?\d{4}[-. ]?\d{4}", phonebook)
# ['010-0000-1234', '010 0000 9876', '010.0000.4321']Wie in Lektion 2 gelernt, ist . in eckigen Klammern ein echter Punkt, und - steht ganz vorn und ist deshalb ein normales Zeichen.
Beweislabor
re.search(r"", text)
Rückgabewert
Ein Quantor hängt sich nur an den einen Baustein direkt vor ihm. Ein Baustein ist ein einzelnes Zeichen, eine Klasse in eckigen Klammern oder eine Kurzschreibweise wie \d. Deshalb heißt ab+ nicht „mehrmals ab“, sondern „ein a, gefolgt von mehreren b“.
re.findall(r"ab+", "abbb abab") # ['abbb', 'ab', 'ab']
re.fullmatch(r"ab+", "abab") # None
re.fullmatch(r"(ab)+", "abab") # <re.Match object; span=(0, 4), match='abab'>Willst du mehrere Zeichen zusammen wiederholen, fasst du sie mit runden Klammern zu einem Baustein zusammen. (ab)+ heißt „ein- oder mehrmals ab“. Klammern haben außer dem Zusammenfassen noch eine zweite wichtige Aufgabe. Die lernst du in Lektion 5.
re.fullmatch liefert nur dann einen Treffer, wenn der ganze String zum Muster passt. Den genauen Unterschied behandeln wir in Lektion 4.
Beweislabor
re.search(r"", text)
Rückgabewert
Quantoren sind von Haus aus gierig (greedy). Sie nehmen sich so viel, wie es der erlaubte Bereich nur zulässt.
re.search(r"\d+", "tel 0100000") # <re.Match object; span=(4, 11), match='0100000'>
re.search(r"\d{2,4}", "123456") # <re.Match object; span=(0, 4), match='1234'>
re.findall(r"\d{2,4}", "123456") # ['1234', '56']\d{2,4} wäre auch mit zwei Ziffern zufrieden, schnappt sich aber zuerst vier. Erst wenn der Rest des Musters scheitert, gibt es eine nach der anderen wieder her. Dieses „Zurückgeben und neu Versuchen“ heißt Backtracking, und in Lektion 8 legt genau das die Detektei lahm. Den genügsamen Quantor +?, der sich möglichst wenig nimmt, lernst du dann auch.
Jetzt sammelst du die Treffer aus der ganzen Liste ein. Nimm an, die Liste von oben steckt im String phonebook.
re.findall gibt die gefundenen Texte als Liste von Strings zurück. So verhält es sich, wenn das Muster keine runden Klammern enthält. Was mit Klammern passiert, siehst du in Lektion 5.
re.findall(r"\d{5}", phonebook) # ['04542', '04545', '04538', '04539']re.finditer gibt einen Iterator zurück, der dir ein Match-Objekt nach dem anderen liefert. Den nimmst du, wenn du auch die Position (span) brauchst.
for m in re.finditer(r"\d{5}", phonebook):
print(m.group(), m.span())
# 04542 (22, 27)
# 04545 (50, 55)
# 04538 (78, 83)
# 04539 (106, 111)re.finditer noch einmal auf.Vorsicht ist hier bei leeren Treffern geboten. *, ? und {,n} erlauben null Wiederholungen und haben deshalb auch an Stellen ohne ein einziges Zeichen Erfolg. findall packt auch diese leeren Treffer als '' ins Ergebnis.
re.findall(r"\d*", "a12b") # ['', '12', '', '']
re.findall(r"\d+", "a12b") # ['12']Ein leerer Treffer vor dem a, dann 12, ein leerer Treffer vor dem b und einer am Ende des Strings. Wenn du etwas einsammeln willst, nimm + oder {1,}, die null Wiederholungen nicht zulassen.
Beweislabor
re.search(r"", text)
Rückgabewert
Eine Telefonnummer besteht hier aus einer Vorwahl bzw. einem Anfang mit 2 bis 3 Ziffern, einem Mittelteil mit 3 bis 4 Ziffern und einem Schluss mit 4 Ziffern. Trennzeichen dürfen da sein oder fehlen. Eine Postleitzahl hat fünf Ziffern.
phones = re.findall(r"\d{2,3}[-. ]?\d{3,4}[-. ]?\d{4}", phonebook)
print(phones)
# ['010-0000-1234', '010 0000 9876', '02-0000-5678', '010.0000.4321', '234-5678-9012']
postcodes = re.findall(r"\d{5}", phonebook)
print(postcodes) # ['04542', '04545', '04538', '04539']Vier Telefonnummern und vier Postleitzahlen sind beisammen. Aber was ist die fünfte Telefonnummer, 234-5678-9012? Die Floristin wirft einen Blick auf den Bildschirm und schüttelt den Kopf. „Das ist keine Telefonnummer. Das ist eine Notiz mit meiner Kartennummer.“
re.search(r"\d{2,3}[-. ]?\d{3,4}[-. ]?\d{4}", "yoon 1234-5678-9012")
# <re.Match object; span=(7, 20), match='234-5678-9012'>Das Muster hat die erste Ziffer 1 von 1234 übersprungen und den Treffer an Position 7 begonnen, mitten in einer Zahl. Dasselbe Missgeschick wie bei 23가4567 in 3-1.
Beweislabor
re.search(r"", text)
Rückgabewert
Fall abgeschlossen — Aus der OCR-Liste wurden 4 Telefonnummern und 4 Postleitzahlen wiederhergestellt und an den Blumenladen übergeben. Offen bleibt, dass ein Teil einer Kartennummer fälschlich als Telefonnummer erkannt wird.
Die Chefin starrt lange auf die letzte Zeile. „Mitten in der Zahl angefangen. Dieses Muster weiß nicht, wo eine Nummer anfängt und wo sie aufhört.“ In der nächsten Lektion lernst du, diese Grenzen ins Muster zu schreiben.
\d{2,3}[-. ]?\d{3,4}[-. ]?\d{4} in 01000001234 (einer Nummer ohne Trennzeichen) findet, und probier es aus.re.findall(r"\d?", "a1")? Wie viele leere Strings sind dabei?re.finditer die Telefonnummern in der Liste und gib Zeile für Zeile die Nummer und ihre Startposition aus.Das Notizbuch der Direktorin
{m} genau m-mal, {m,n} m- bis n-mal, {m,} mindestens m-mal, {,n} null- bis n-mal. Keine Leerzeichen am Komma.
* null- oder mehrmals, + ein- oder mehrmals, ? null- oder einmal.
Ein Quantor gilt nur für den Baustein direkt davor. ab+ und (ab)+ sind verschieden.
Quantoren sind gierig. Sie nehmen sich so viel wie möglich.
re.findall liefert eine Liste von Strings, re.finditer einen Iterator über Match-Objekte.
Muster, die null Wiederholungen erlauben, erzeugen leere Treffer ''. Zum Einsammeln + nehmen.
← Zurück
Lektion 2 · Der Fluchtwagen: Zeichenklassen
Weiter →
Lektion 4 · Die falschen Anmeldungen: Anker und Validierung
Über neue Lektionen informiert werden
Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.
R
ReflexKR
Python und Reflex zum Anfassen. Alle Beispiele wurden mit Reflex 0.10.0 ausgeführt und geprüft.
ReflexKR ist kostenlos und ohne Werbebanner. Wenn es dir geholfen hat, kannst du es mit einem Kaffee unterstützen. ☕ Spendier uns einen Kaffee
Hinweis zu Affiliate-Links© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Fragen & Antworten
Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.