Kostenloser Regex-Spickzettel
Interaktive Referenzanleitung für reguläre Ausdrücke.
Test-Muster
Anleitung
- Stöbern Sie in den Musterkategorien oder verwenden Sie die Suche, um bestimmte Muster zu finden.
- Geben Sie ein Regex-Muster in das Feld „Test-Muster" und Beispieltext in „Test-Text" ein.
- Schalten Sie Flags (global, ohne Groß-/Kleinschreibung, Multiline) um und sehen Sie Treffer sofort hervorgehoben.
Häufig gestellte Fragen
Was ist ein regulärer Ausdruck?
Ein regulärer Ausdruck (Regex oder Regexp) ist ein Muster, das verwendet wird, um Text zu finden, zu durchsuchen und zu ersetzen. Es nutzt Sonderzeichen und Syntax, um zu definieren, welche Strings gefunden werden sollen.
Was machen die Flags?
Global (g) findet alle Treffer. Case Insensitive (i) ignoriert Groß-/Kleinschreibung. Multiline (m) behandelt ^ und $ als Zeilengrenzen statt als String-Grenzen.
Kann ich diese Cheatsheet in meinem Code verwenden?
Ja! Sobald Sie ein Muster hier getestet und seine Funktion überprüft haben, kopieren Sie das Regex-Muster direkt in Ihr JavaScript, Python oder eine andere Programmiersprache.
Eine kurze Geschichte der Mustersprache
Reguläre Ausdrücke begannen als ein Stück theoretische Informatik. Stephen Kleene definierte 1956 in einem Aufsatz über neuronale Netze die «regulären Mengen»; Ken Thompson baute sie 1968 mit grep in Unix ein. Henry Spencers Open-Source-Regex-Bibliothek (Mitte der 1980er) wurde Grundlage vieler späterer Implementierungen. Larry Wall erweiterte die Syntax in Perl drastisch, und seine «Perl-compatible regular expressions» (PCRE) wurden zum De-facto-Standard, dem die meisten modernen Sprachen folgten. Heute gibt es mehrere eng verwandte, aber subtil unterschiedliche Regex-Geschmacksrichtungen, und ein Muster, das in einer Engine funktioniert, funktioniert in einer anderen nicht immer identisch.
Die Engine, in der dein Muster lebt
Dieselbe Syntax kann in verschiedenen Engines Verschiedenes bedeuten. Die großen Familien:
- POSIX BRE (Basic Regular Expressions), verwendet vom Standardmodus von
grep, vonsed. Viele Metazeichen brauchen Backslash-Escaping:(,),{,},+,?,|sind ohne Escape literal. - POSIX ERE (Extended Regular Expressions), verwendet von
egrep,awk. Die obigen Metazeichen funktionieren ohne Escaping. - PCRE (Perl-Compatible Regular Expressions), erweitert ERE um Lookarounds, atomare Gruppen, benannte Captures und Backreferences. Verwendet von PHP und den meisten modernen Sprachen. Die von Perl abgeleiteten Kurzformen
\d/\w/\ssind PCRE, JavaScript, .NET, Java und Python gemeinsam. - JavaScript RegExp, nahe an PCRE, aber mit nennenswerten Unterschieden. ES2018 fügte Lookbehinds, benannte Capture-Gruppen, das
s-Dotall-Flag und Unicode-Property-Escapes über dasu-Flag hinzu. Dasv-Flag für Mengennotation kam mit ES2024. - Pythons
reund Pythonsregex,reist in der Standardbibliothek; das Drittmodulregexergänzt um Unicode-bewusste Funktionen, Lookbehinds variabler Breite und andere PCRE-artige Erweiterungen. - RE2 (Googles Bibliothek, in Go verwendet), garantiert lineare Zeit, unterstützt aber keine Backreferences oder Lookarounds. Der Trade-off: vorhersagbare Performance, weniger Features.
Der interaktive Tester dieses Spickzettels läuft in JavaScript, das Muster wird also von der JS-Engine des Browsers ausgewertet. Muster, die hier funktionieren, können sich in Python oder PHP anders verhalten. Die meisten Unterschiede liegen in fortgeschrittenen Features (Lookbehinds, Unicode-Property-Escapes, Backreferences) und nicht in der Basissyntax.
Die zentralen Bausteine
Fast jedes Regex-Muster wird aus diesen Elementen aufgebaut:
- Literale, entsprechen sich selbst.
catmatcht den Substring «cat». - Anker,
^(Anfang von String / Zeile),$(Ende),\b(Wortgrenze),\B(Nicht-Wortgrenze). - Zeichenklassen,
[abc]matcht a, b oder c.[^abc]negiert.[a-z]ist ein Bereich. Kurzformen:\d(Ziffer),\w(Wortzeichen: Buchstabe, Ziffer, Unterstrich),\s(Whitespace), und Großbuchstaben-Versionen für die Negation (\D,\W,\S). - Quantoren,
?(0 oder 1),*(0 oder mehr),+(1 oder mehr),{n},{n,},{n,m}. Standardmäßig gierig (so viel wie möglich matchen); füge?für faul hinzu:*?,+?,??. - Gruppen,
(...)einfangend,(?:...)nicht-einfangend,(?<name>...)benannt (PCRE / JS / Python). - Alternation,
cat|dogmatcht eines von beiden. - Lookarounds,
(?=...)positives Lookahead,(?!...)negatives Lookahead,(?<=...)positives Lookbehind,(?<!...)negatives Lookbehind. Matchen ohne zu konsumieren. - Backreferences,
\1,\2(nummeriert),\k<name>(benannt). Matchen denselben Text, den die zugehörige Erfassung gematcht hat. - Flags,
g(global),i(Groß-/Kleinschreibung ignorieren),m(Multiline:^und$matchen Zeilengrenzen),s(Dotall:.matcht auch Zeilenumbrüche),u(Unicode),y(Sticky in JS).
Muster, die zu merken sich lohnt
Eine Handvoll Muster taucht so oft auf, dass es sich lohnt, sie im Kopf zu haben:
| Verwendung | Muster |
|---|---|
| E-Mail (einfach) | ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ |
| URL | https?://[^\s]+ |
| US-Telefonnummer | \(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4} |
| ISO-Datum (YYYY-MM-DD) | \d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) |
| IPv4-Adresse (ohne Oktett-Validierung) | \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b |
| Hex-Farbe | ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$ |
| Whitespace am Anfang/Ende einer Zeile | ^\s+|\s+$ |
| Mehrere aufeinanderfolgende Leerzeichen | \s{2,} |
Eine Anmerkung zur E-Mail-Regex: Vollständige RFC-5322-E-Mail-Validierung braucht eine 6.000 Zeichen lange Monster-Regex. Die einfache Form oben akzeptiert 99% der echten E-Mail-Adressen und weist keine legitime ab; in der Produktion lieber eine Bestätigungs-E-Mail schicken, statt zu versuchen, die Syntax perfekt zu validieren.
Gierig vs. faul: eine häufige Überraschung
Standardmäßig sind Quantoren gierig: Sie matchen so viel wie möglich, solange das Gesamtmuster noch passt. Also matcht <.+> gegen <a>text</a> die gesamte Sache, nicht nur <a>, weil .+ so viel greift, wie es kann. Um den kürzestmöglichen String zu matchen, hänge ? an den Quantor an: <.+?> matcht <a> und dann </a> separat. Die Wahl zwischen gierig und faul ist eine der häufigsten Quellen von «Warum matcht meine Regex nicht das, was ich erwartet habe»-Bugs.
Katastrophales Backtracking und ReDoS
Manche Regex-Muster können auf bestimmten Eingaben exponentiell lange zum Scheitern brauchen, eine Klasse von Denial-of-Service-Schwachstellen namens ReDoS (Regular Expression Denial of Service). Klassische Übeltäter sind verschachtelte Quantoren wie (a+)+ oder (a|aa)+, angewendet auf einen langen String von as gefolgt von einem nicht passenden Zeichen. Die Engine probiert jede mögliche Aufteilung des Strings, bevor sie aufgibt, und die Anzahl der Möglichkeiten ist exponentiell.
Reale Vorfälle: Cloudflares Ausfall 2019 wurde durch eine in einer WAF-Regel deployte Regex ausgelöst, die auf bestimmten Eingaben katastrophal backtrackte. Stack Overflow hatte im Juli 2016 einen ähnlichen Vorfall: eine Post-Trim-Regex (^[\s]+|[\s]+$) traf auf exponentielles Backtracking bei einem einzelnen Kommentar mit etwa 20.000 aufeinanderfolgenden Whitespace-Zeichen und legte die Seite 34 Minuten lahm. Defensive Gewohnheiten: verschachtelte Quantoren vermeiden, atomare Gruppen ((?>...)) bevorzugen, wo unterstützt, und für nicht vertrauenswürdigen Input RE2 / lineare Zeit-Engines erwägen.
Sprachspezifische Eigenheiten, die man kennen sollte
- JavaScript: Backslashes brauchen in String-Literalen doppeltes Escaping (
"\\d"), aber nicht in Regex-Literalen (/\d/). Verwende, wo möglich, die Regex-Literal-Form. - Python: Verwende Raw-Strings (
r"\d+"), um Backslash-Probleme zu vermeiden. Dasre-Modul ist in der Standardbibliothek;regexauf PyPI fügt Extra-Features hinzu. - Java: Backslashes brauchen vierfaches Escaping (
"\\\\d"für\d), weil Java-String-Literale\als Escape verwenden und der Regex-Compiler dann\\dsieht. - Bash: Regex-Matching in
[[ string =~ pattern ]]verwendet POSIX ERE. Die Quoting-Regeln sind heikel; konsultiereman bash. - Go: Verwendet RE2, also sind Backreferences und Lookarounds nicht verfügbar. Trade-off: lineare Zeitgarantie.
Wann man Regex NICHT verwenden sollte
Jamie Zawinskis berühmte Zeile von 1997: «Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems.»
- Parse HTML / XML nicht mit Regex. Verwende einen echten Parser (DOMParser im Browser, BeautifulSoup in Python, jsoup in Java usw.). Die verschachtelte Struktur von HTML liegt fundamental jenseits dessen, was Regex sauber ausdrücken kann.
- Parse JSON nicht mit Regex. Verwende JSON.parse / Standardbibliothek-JSON-Parser.
- Validiere E-Mails nicht streng mit Regex. Schick eine Bestätigungs-E-Mail; das ist der einzig zuverlässige Test.
- Schreib keinen CSV-Parser als Regex. Anführungszeichenfelder mit eingebetteten Kommas, escapte Anführungszeichen und mehrzeilige Werte wachsen schnell aus dem heraus, was Regex sauber handhabt.
- Versuche nicht, ausgeglichene Klammern zu matchen. Standard-Regex kann das nicht (es ist eine kontextfreie Sprache); manche PCRE-Engines haben Rekursionsfeatures, die mogeln, aber ein echter Parser ist sauberer.
Häufige Fehler
- Vergessen, Sonderzeichen zu escapen.
.,*,?,+,(,),[,],{,},\,^,$,|,/haben alle Sonderbedeutungen. Um sie literal zu matchen, mit Backslash präfixieren. - Gierige Quantoren konsumieren zu viel. Füge
?für faules Matching hinzu, wenn du den kürzestmöglichen Match willst. - Das globale Flag vergessen und sich wundern, warum nur der erste Match angezeigt wird. JavaScripts
String.prototype.match()gibt ohne dasg-Flag nur den ersten Match zurück. - Katastrophales Backtracking bei langen Eingaben. Verschachtelte Quantoren wie
(a+)+können bei bestimmten Eingaben hängen. Mit Edge Cases testen. - Annehmen, dieselbe Regex verhalte sich in jeder Sprache gleich. Lookbehinds, Unicode-Escapes und Zeichenklassen-Kurzformen variieren alle.
- Versuchen, E-Mails zu streng zu validieren. Die technisch korrekte RFC-5322-Regex ist nicht wartbar; eine einfache Regex plus Bestätigungs-E-Mail-bei-Anmeldung ist das funktionierende Muster.
- Regex auf HTML, JSON oder CSV verwenden. Verwende einen richtigen Parser; die Zeit, die du am Anfang sparst, verlierst du an Bugs.
Weitere häufig gestellte Fragen
Warum funktioniert mein Muster hier, scheitert aber in meinem Code?
Die häufigste Ursache sind Engine-Unterschiede. JavaScripts RegExp unterstützt manche Features, die PCRE hat, nicht (und umgekehrt). Häufige Stolpersteine: Lookbehinds wurden spät zu JS hinzugefügt (ES2018), die Syntax benannter Gruppen unterscheidet sich leicht, Unicode-Property-Escapes brauchen das u-Flag, und POSIX-Zeichenklassen wie [[:alpha:]] fehlen in JS größtenteils. Teste in der Engine, in der du deployst.
Gibt es einen «globalen» Weg, über mehrere Zeilen zu matchen?
Zwei Flags arbeiten zusammen. Das m-Flag (Multiline) lässt ^ und $ Anfang und Ende jeder Zeile matchen, statt der ganzen Zeichenkette. Das s-Flag (Dotall) lässt . auch Newline-Zeichen matchen. Kombiniert mit g für global kannst du zeilenübergreifende Muster schreiben, die jeden Match finden: /^foo.+$/gms.
Werden meine Muster und Testtexte irgendwohin geschickt?
Nein. Das Pattern-Matching nutzt die in den Browser eingebaute JavaScript-RegExp-Engine; nichts wird auf einen Server hochgeladen. Das ist wichtig, wenn du Muster gegen echte Production-Logdaten, interne API-Antworten oder sensiblen Inhalt testest.
Sollte ich Lookbehinds lernen?
Nützlich, aber nicht essenziell. Lookbehinds erlauben dir, Text zu matchen, dem etwas vorausgeht, ohne dieses «etwas» in den Match aufzunehmen. Beispiel: (?<=\$)\d+ matcht Ziffern hinter einem Dollarzeichen, ohne das Dollarzeichen zu konsumieren. Sie werden in PCRE, modernem JavaScript (ES2018+) und Pythons regex-Modul unterstützt. Wenn du portable Muster schreibst, prüfe zuerst die Ziel-Engine.
Warum (?:...) statt (...) verwenden?
Nicht-einfangende Gruppen ((?:...)) sind etwas schneller, belegen keinen Slot im Capture-Array und halten deine Match-Ergebnisse sauber. Verwende sie, wann immer du Gruppierung für Alternation oder Quantifizierung brauchst, aber den gematchten Text nicht extrahieren musst. (http|https):// erzeugt eine Erfassung, die du vielleicht nicht brauchst; (?:http|https):// nicht.
Was ist der richtige Weg, Unicode-Zeichen zu matchen?
In JavaScript füge das u-Flag hinzu und verwende Unicode-Property-Escapes: /\p{Letter}+/gu matcht Buchstabenfolgen in jeder Schrift. Ohne das u-Flag matcht \w nur ASCII-Wortzeichen. Pythons re-Modul ist in Python 3 standardmäßig Unicode-bewusst. Java braucht Pattern.UNICODE_CHARACTER_CLASS. Die meisten Engines haben irgendeine Möglichkeit, Unicode-bewusst zu sein; siehe die Doku deiner.