R

ReflexKR

Reflex-Dokumentation

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

Reguläre Ausdrücke zum Ansehen
Lektion 9

Zeit 6:40–7:30

Die Regeln des Tresors: Lookaround

CASE-009

Grep & Co. Datendetektei

Fallakte

Die Regeln des Tresors

Auftraggeber

Direktorin Han Byeol

Beweismittel

Der alte Tresor der Detektei, sechs Kandidaten für das neue Passwort und das Kassenbuch im Tresor.

Zum Abschluss des Falls

Die neuen Passwortregeln (mindestens 8 Zeichen, je mindestens eine Ziffer, ein Kleinbuchstabe und ein Sonderzeichen) mit einem einzigen Muster prüfen und die Beträge im Kassenbuch mit Tausenderkommas versehen.

Die Direktorin hockt sich vor den alten Tresor in der Ecke. „Dass der Backtracker den Tresor erwähnt, soll uns nur Angst machen. Trotzdem ändern wir heute das Passwort. Und diesmal halten wir uns an die Regeln.“

Für das neue Passwort gelten drei Regeln, die Reihenfolge ist egal. Ihr Zettel ist auf Koreanisch: (1) mindestens 8 Zeichen, (2) je mindestens eine Ziffer, ein Kleinbuchstabe und ein Sonderzeichen, (3) alles mit einem einzigen regulären Ausdruck prüfen. Darunter stehen die Kandidaten (후보).

규칙 1. 8자 이상
규칙 2. 숫자, 소문자, 특수문자가 각각 하나 이상
규칙 3. 이 모든 걸 정규식 하나로 검사한다

후보:
vault2026!
vault2026
VAULT2026!
v!2
longpassword!
safe#2026box

Dir fällt der Satz von der Karte wieder ein: „Vorausgesetzt, ihr könnt alle an derselben Stelle prüfen.“ Genau darum geht es heute.

9-1. Syntax, die keine Zeichen prüft, sondern Positionen (6 Min.)

Erinnere dich an ^, $ und \b aus Lektion 4. Sie fressen kein einziges Zeichen und prüfen nur eine Position: „Ist hier der Anfang?“, „Ist hier eine Wortgrenze?“ Solche Treffer heißen Treffer der Breite null (zero-width).

re.findall(r"\b", "hi yo")      # ['', '', '', '']
re.sub(r"\b", "|", "hi yo")     # '|hi| |yo|'

\b hat vier leere Strings gefunden, also vier Positionen. Mit Lookaround, um das es heute geht, baust du solche Positionsprüfungen mit beliebigen eigenen Bedingungen.

9-2. Prüfen, was dahinter kommt: (?=...) (8 Min.)

X(?=Y) findet „ein X, auf das Y folgt“. Y wird nur geprüft und gehört nicht zum Treffer. Das nennt man Lookahead.

re.findall(r"\d+(?=원)", "3000원짜리 5개, 합계 15000원")   # ['3000', '15000']

Der Text ist ein koreanischer Preiszettel: 원 ist Won, die koreanische Währung, 개 heißt „Stück“, 합계 „Summe“. Die 5 in 5개 fällt weg, weil kein 원 dahinter steht, und in den gefundenen Zahlen steckt kein 원. Ideal, wenn du „Zahlen, die auf Won enden“ suchst, aber nur die Zahl haben willst.

Beweislabor

re.search(r"", text)

Rückgabewert

Mit \d+ allein wird auch die Stückzahl 5 gefangen. Häng ein Lookahead an, damit nur Zahlen übrig bleiben, auf die 원 folgt.

9-3. Was nicht dahinter kommen darf: (?!...) (6 Min.)

X(?!Y) ist das Gegenteil: „ein X, auf das Y nicht folgt“. Das heißt negatives Lookahead.

re.findall(r"\b(?!tmp)\w+", "tmp_log report tmpfile final")   # ['report', 'final']
re.findall(r"\d{3}(?!\d)", "12345 678")                       # ['345', '678']
  • Die erste Zeile bedeutet „Wörter, die nicht mit tmp anfangen“. Direkt nach der Wortgrenze wird geprüft, dass dort kein tmp steht.
  • Die zweite Zeile bedeutet „drei Ziffern, nach denen keine Ziffer mehr kommt“, also die letzten drei Ziffern eines Zahlenblocks.

9-4. Mehrere Regeln: Lookaheads aneinanderhängen (8 Min.)

Bedingungen der Art „dies muss drin sein, das auch und jenes auch“, wie bei Passwortregeln, schreibst du als Lookaheads nebeneinander.

pw = r"(?=.*\d)(?=.*[a-z])(?=.*[^\w\s]).{8,}"
Bausteinprüft
(?=.*\d)irgendwo steht eine Ziffer
(?=.*[a-z])irgendwo steht ein Kleinbuchstabe
(?=.*[^\w\s])irgendwo steht ein Sonderzeichen (weder Buchstabe, Ziffer, Unterstrich noch Leerraum)
.{8,}frisst tatsächlich mindestens 8 Zeichen

Alle drei Lookaheads prüfen an derselben Stelle (ganz vorn). Weil sie keine Zeichen fressen, bleibt die Position nach jedem gleich, und die nächste Bedingung startet wieder ganz vorn. Aneinandergehängt ergeben sie deshalb ein „und“ (AND).

cands = ["vault2026!", "vault2026", "VAULT2026!", "v!2", "longpassword!", "safe#2026box"]
[c for c in cands if re.fullmatch(pw, c)]   # ['vault2026!', 'safe#2026box']

Beweislabor

re.search(r"", text)

Rückgabewert

.{8,} achtet nur auf die Länge. Stell die Bedingungen für Ziffer, Kleinbuchstabe und Sonderzeichen als Lookaheads davor.

Dots Tipp

Ein Lookahead späht nur kurz nach vorn, die Pfoten bleiben, wo sie sind. Ich sitze ja auch auf dem Fensterbrett und schaue nur hinaus, rüber springe ich nicht. Deshalb bin ich, egal wie oft ich hinausschaue, immer noch am selben Platz.

9-5. Was davor stand: (?<=...) (?<!...) (8 Min.)

Dreh die Richtung um, und du hast Lookbehind. (?<=Y)X heißt „ein X, vor dem Y steht“, (?<!Y)X heißt „ein X, vor dem kein Y steht“.

re.findall(r"(?<=\$)\d+", "$30 and 40 and $5")      # ['30', '5']
re.findall(r"(?<!\$)\b\d+", "$30 and 40 and $5")    # ['40']

Lookbehind hat eine Einschränkung: Pythons re muss fest wissen, wie weit es zurückschaut.

re.compile(r"(?<=a+)b")      # PatternError: look-behind requires fixed-width pattern
re.compile(r"(?<=ab|cd)e")   # in Ordnung: beide Alternativen sind 2 Zeichen lang
re.compile(r"(?<=a|bc)d")    # PatternError: look-behind requires fixed-width pattern

Mehrere Alternativen sind erlaubt, solange alle gleich lang sind. Sind sie unterschiedlich lang, teilst du das Lookbehind in zwei auf und gruppierst sie getrennt, etwa (?:(?<=a)|(?<=bc))d.

Beweislabor

re.search(r"", text)

Rückgabewert

\$\d+ liefert das $ mit. Verschiebe \$ in ein Lookbehind, damit der Rückgabewert ['30', '5'] lautet.

9-6. Das Kassenbuch im Tresor: Tausenderkommas (4 Min.)

Im Kassenbuch aus dem Tresor kleben die Ziffern zusammen, etwa 1234567, und sind schwer zu lesen. Du musst nur die Positionen finden, an die ein Komma gehört, und dort eins einsetzen. Positionen suchen ist ein Fall für Lookaround.

re.sub(r"(?<=\d)(?=(?:\d{3})+(?!\d))", ",", "1234567 and 89 and 1000")
# '1,234,567 and 89 and 1,000'

So liest du es: „Eine Position, vor der eine Ziffer steht ((?<=\d)) und nach der ein oder mehrere Dreierblöcke aus Ziffern folgen ((?:\d{3})+), nach denen die Zahl endet ((?!\d)).“ Diese Position ist kein Zeichen, also löscht sub nichts, sondern schiebt nur das Komma ein.

Mit einer Gruppe im Lookahead findest du sogar überlappende Treffer. Der Trick: Die Position rückt jeweils ein Zeichen weiter, und die Gruppe holt die beiden Zeichen an dieser Stelle heraus.

re.findall(r"(?=(\w\w))", "abc")   # ['ab', 'bc']

Beweislabor

re.search(r"", text)

Rückgabewert

Der Ersatz ist ein einzelnes Komma. Nur wenn das Muster Positionen statt Zeichen findet, verschwinden keine Ziffern.

Den Fall lösen (10 Min.)

Du stellst den Prüfer fertig und siebst die Kandidaten. Die Ausgabe ist koreanisch: 통과 heißt „bestanden“, 탈락 heißt „durchgefallen“.

pw = re.compile(r"(?=.*\d)(?=.*[a-z])(?=.*[^\w\s]).{8,}")
for c in cands:
    print(f"{c:<14} {'통과' if pw.fullmatch(c) else '탈락'}")
# vault2026!     통과
# vault2026      탈락
# VAULT2026!     탈락
# v!2            탈락
# longpassword!  탈락
# safe#2026box   통과

Die Direktorin nimmt keinen der beiden, die bestanden haben. „Sobald es auf einer Kandidatenliste steht, ist es kein Passwort mehr.“ Dann legt sie selbst, ohne dass jemand zusieht, ein neues Passwort fest, das die Regeln erfüllt, und legt nur den Prüfer in den gemeinsamen Werkzeugkasten der Detektei.

Fall abgeschlossen — Ein Werkzeug gebaut, das die Passwortregeln des Tresors mit drei Lookaheads prüft. Von sechs Kandidaten haben nur zwei die Regeln erfüllt. Das Passwort hat die Direktorin selbst geändert. Die Beträge im Kassenbuch mit Tausenderkommas aufbereitet.

Übungen

  1. Ergänze die Regeln um „mindestens ein Großbuchstabe“. Welche Kandidaten überleben?
  2. Hol aus "price: 1200won, tax: 120won" per Lookahead nur die Zahlen vor won heraus.
  3. Was liefert re.findall(r"(?<!\d)\d{2}(?!\d)", "1 22 333 44")? Rate zuerst. Warum kommt kein Teil von 333 heraus?

Die Spur des Backtrackers

(a+)+$

Den Tresor lasse ich in Ruhe. Stattdessen habe ich Kommissar Kang auf dem Revier drei Briefe geschickt. Könnt ihr beweisen, dass sie von derselben Person stammen? Gewohnheiten bleiben in den Buchstaben hängen.

Das Notizbuch der Direktorin

  • Lookaround sind Treffer der Breite null. Sie fressen keine Zeichen und prüfen nur Positionen (wie ^ $ \b).

  • X(?=Y): ein X, auf das Y folgt. X(?!Y): ein X, auf das kein Y folgt.

  • (?<=Y)X: ein X, vor dem Y steht. (?<!Y)X: ein X, vor dem kein Y steht. Lookbehind nur mit fester Länge.

  • Aneinandergehängte Lookaheads sind ein AND: (?=.*\d)(?=.*[a-z])(?=.*[^\w\s]).{8,}

  • sub an gefundenen Positionen löscht nichts, sondern schiebt ein: Tausenderkommas.

  • Mit einer Gruppe im Lookahead wie (?=(\w\w)) holst du überlappende Treffer heraus.

← Zurück

Lektion 8 · Die Herausforderung des Backtrackers: gierig, genügsam, possessiv

Weiter →

Lektion 10 · Gleiche Masche: Rückverweise und Bedingungen

Über neue Lektionen informiert werden

Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.

Erhoben: deine E-Mail-Adresse · Zweck: Hinweise auf neue Lektionen oder den Start dieses Kurses · Speicherdauer: bis du die Löschung verlangst. Keine andere Nutzung, keine Weitergabe. Antworte einfach auf eine Benachrichtigung, dann löschen wir sie sofort.

Fragen & Antworten

Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.

Wird als reiner Text angezeigt, ohne Links oder Formatierung.

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
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex