Meine Regex funktioniert im Tester, aber nicht im Code — warum

Das Muster ist fast nie das Problem. Es sind Escaping, Flags oder eine andere Regex-Engine — und jede Ursache hat ein charakteristisches Symptom, das dir verrät, mit welcher der drei du es zu tun hast.

Du baust ein Muster in einem Online-Tester, es passt perfekt, du fügst es in deinen Code ein und es trifft auf nichts zu. Die Regex hat sich nicht geändert, also hat sich etwas darum herum geändert. In der Praxis ist es eines von drei Dingen: das Muster wurde durch String-Escaping verstümmelt, die Flags sind nicht mitgereist, oder deine Sprache nutzt eine andere Regex-Engine als der Tester.

Escaping: das Muster in deinem Code ist nicht das, was du geschrieben hast

Das ist mit Abstand die häufigste Ursache und tritt immer dann auf, wenn die Regex in einem String statt in einem nativen Regex-Literal steht. In einem String ist der Backslash selbst ein Escape-Zeichen und wird verbraucht, bevor die Regex-Engine ihn überhaupt sieht. Dein \d wird zu einem einfachen d, und \. wird zu einem literalen Punkt, der nun auf jedes Zeichen passt. Das Muster, das die Engine erhält, ist tatsächlich ein anderes als das getippte. Die Lösung unterscheidet sich je nach Sprache: in JavaScript bevorzuge die Literalform /\d+/ gegenüber new RegExp("\\d+"); in Python nutze einen Raw-String, r"\d+"; in Java und C# musst du jeden Backslash verdoppeln oder C#s Verbatim-Strings @"..." verwenden.

Flags werden separat gesetzt und nicht mitkopiert

Online-Tester packen die Flags in ein eigenes Kästchen neben das Muster — wenn du also markierst und kopierst, nimmst du das Muster mit und lässt die Flags zurück. Drei sind besonders wichtig. Das m-Flag ändert die Bedeutung von ^ und $ von "Anfang und Ende der gesamten Zeichenkette" zu "Anfang und Ende jeder Zeile"; ohne es scheitert ein Muster, das gegen einen mehrzeiligen Testtext funktionierte. Das s-Flag lässt . auch Zeilenumbrüche treffen, was es standardmäßig nicht tut. Und das i-Flag für Groß-/Kleinschreibungsunabhängigkeit ist das, bei dem man am häufigsten vergisst, dass es eingeschaltet war.

Das g-Flag hat seine eigene Falle

In JavaScript ist eine Regex mit g-Flag zustandsbehaftet: sie führt eine lastIndex-Eigenschaft, die nach jedem Treffer weiterrückt. Verwendest du dasselbe Regex-Objekt mit .test() in einer Schleife wieder, bekommst du bei identischer Eingabe abwechselnd true und false — das sieht nach Nichtdeterminismus aus und ist zermürbend zu debuggen. Erzeuge die Regex jedes Mal neu, lass das g-Flag weg, wenn du nur einen Boolean brauchst, oder setze lastIndex zwischen den Aufrufen auf null.

Nicht jede Engine spricht denselben Dialekt

Die meisten Online-Tester nutzen standardmäßig PCRE, den Perl-kompatiblen Dialekt. Dein Code tut das vielleicht nicht. Lookbehind-Assertions, benannte Gruppen und possessive Quantoren werden unterschiedlich unterstützt. Das krasseste Beispiel ist RE2, verwendet von Go und mehreren Datenbanken, das Rückwärtsreferenzen und Lookahead bewusst komplett weglässt, damit die Matching-Zeit linear bleibt — ein Muster, das darauf baut, scheitert nicht bloß, es lässt sich gar nicht kompilieren. Hat dein Tester eine Engine-Auswahl, stelle sie auf deine tatsächliche Sprache, bevor du das Muster baust, nicht erst wenn es bricht.

Teiltreffer gegen Volltreffer

Tester zeigen dir fast immer jeden Teiltreffer im Text hervorgehoben, aber viele Sprach-APIs stellen eine andere Frage. Javas matches() verlangt, dass das Muster die gesamte Eingabe konsumiert, während find() irgendwo im Text sucht — ein Muster, das im Tester fröhlich leuchtet, liefert also false aus matches(). Python hat dieselbe Dreiteilung zwischen re.match, re.search und re.fullmatch. Wirkt dein Muster korrekt, liefert aber false, prüfe zuerst, welche dieser Funktionen du aufgerufen hast, bevor du die Regex anfasst.

Der eine Debugging-Schritt, der es am schnellsten findet

Gib das kompilierte Muster zur Laufzeit aus — nicht die Quellzeile, sondern den tatsächlichen Wert, den die Engine bekommen hat. In JavaScript ist das String(meineRegex), in Python print(muster.pattern). Weicht das Gesehene vom Geschriebenen ab, ist es ein Escaping-Problem und du hast es in einem Schritt gefunden. Stimmt es exakt überein, liegt es an Flags oder Dialekt — und du hast zwei Drittel der Möglichkeiten ohne Raten ausgeschlossen.

Unser Regex-Tester zeigt Muster, Flags und Treffer nebeneinander und hebt Gruppen beim Tippen hervor, sodass du die exakte Kombination aus Muster und Flags bestätigen kannst, bevor sie in deinen Code wandert. Er läuft in deinem Browser, du kannst also gefahrlos mit echten Daten testen.

→ Regex-Tester