Regex verstehen – Grundlagen, Spickzettel und Praxisbeispiele

Eine kompakte Einführung in reguläre Ausdrücke (Regex). Oben steht ein Spickzettel
zum schnellen Nachschlagen, darunter die Erklärungen für das „wie und warum“. Regex
begegnet überall dort, wo Text gegen ein Muster geprüft wird – in Server-Configs, beim
URL-Routing, in Logfiltern und bei der Eingabevalidierung. Wer die Grundzeichen kennt,
spart sich viel Rätselraten.


Spickzettel

Die wichtigsten Zeichen

Zeichen Bedeutung
. ein beliebiges einzelnes Zeichen
* das Zeichen davor: null- oder mehrmals
+ das Zeichen davor: ein- oder mehrmals
? das Zeichen davor: null- oder einmal (optional)
\ Escape – macht das nächste Zeichen wörtlich
^ Anfang der Zeichenkette
$ Ende der Zeichenkette
[...] eine Zeichenklasse, z. B. [a-z0-9-]
(...) Gruppe (zusammenfassen, Rückbezug)
| oder, z. B. (caldav|carddav)
{n,m} das Zeichen davor n- bis m-mal

Drei Merksätze, die die meisten Fehler verhindern

  1. * bezieht sich auf das Zeichen davor. Eine echte Wildcard ist .* – erst ein
    „beliebiges Zeichen“ (.), dann „beliebig oft“ (*).
  2. Escapt wird nur, was wörtlich gemeint ist – die echten Trennpunkte (\.),
    nie der *.
  3. Der Trennpunkt ist eine Sicherheitsgrenze. Ohne ihn matcht das Muster fremde
    Namen, die nur zufällig auf denselben Stamm enden.

Fertige Bausteine

.*                      irgendwas (beliebig viele beliebige Zeichen)
\.                      ein echter Punkt
[a-z0-9-]+              ein gültiges Hostnamen-Label
^...$                   Muster fest an Anfang und Ende verankern

# Apex + alle Subdomains, sicher verankert:
^https://(.+\.)?beispiel\.com$

Wo Regex auftaucht

Man stolpert öfter über Regex, als man denkt – meist ohne dass „Regex“ draufsteht:

  • Webserver / Reverse Proxy: RewriteRule/RewriteCond in Apache, location ~
    in nginx, ACLs in HAProxy zum Routen nach Host oder Pfad
  • Office-/Collaboration-Dienste wie Collabora CODE: die aliasgroup-Einträge sind
    eine Allow-Liste erlaubter Hosts und werden als Regex ausgewertet
  • Cloud-Plattformen wie Nextcloud oder OpenCloud: Host- und Trusted-Domain-Prüfungen
  • Webabfragen und APIs: URL-Pfade matchen, Query-Parameter validieren, Routen definieren
  • Logfilter, grep, Validierungen aller Art

Die Mechanik ist überall dieselbe – ein einmal verstandenes Muster trägt durch alle
diese Werkzeuge.

Der zentrale Denkfehler: *. ist nicht .*

Das ist der mit Abstand häufigste Stolperstein, besonders für alle, die von
Datei-Wildcards (Glob) kommen.

  • Im Dateisystem bedeutet *.txt „alles, das auf .txt endet“. Dort ist * der
    Platzhalter für „beliebig viel“.
  • In Regex ist * kein Platzhalter, sondern ein Wiederholungs-Operator: Er
    bezieht sich immer auf das Zeichen direkt davor und heißt „davon null- oder
    mehrmals“.

Ein * ganz am Anfang ist deshalb kein harmloser Platzhalter, sondern in den meisten
Engines ein Syntaxfehler – es gibt nichts davor, das wiederholt werden könnte.

Die echte Wildcard in Regex ist die Kombination .*:

  • . = irgendein Zeichen
  • * = davon beliebig viele
  • .* = „beliebig viele beliebige Zeichen“

Merksatz: * braucht immer einen Vorgänger. Für „irgendwas“ ist der Vorgänger .,
also .*.

Escaping: \ macht Zeichen wörtlich

Viele Zeichen haben in Regex eine Sonderbedeutung. Will man sie als das echte,
buchstäbliche Zeichen meinen, stellt man einen Backslash voran:

  • \. = ein echter Punkt (statt „irgendein Zeichen“)
  • \* = ein echter Stern (statt Wiederholungs-Operator)

Wichtig dabei – und genau hier verheddert man sich gern:

Escapt wird nur, was wörtlich gemeint ist.

In einem Hostnamen wie kunde1.beispiel.com sind die Punkte echte Trennzeichen –
also \.. Den * aus .* escapt man dagegen nicht, denn man will ja seine
Wiederholungs-Bedeutung. \* würde nach einem buchstäblichen Stern im Text suchen,
den es in Hostnamen nie gibt.

Nebenbei: Ein unescapter Punkt funktioniert in der Praxis oft trotzdem, weil .
ja „irgendein Zeichen“ matcht – und das schließt den echten Punkt mit ein. beispiel.com
trifft also beispiel.com, aber theoretisch auch beispielXcom. Für reale Hostnamen
egal, sauber ist trotzdem beispiel\.com.

.* vs .+

  • .* = null oder mehr Zeichen
  • .+ = ein oder mehr Zeichen

Beim Matchen einer Subdomain steht vor dem Trennpunkt immer mindestens ein Zeichen
(kunde1, x, …). .+ bildet das einen Tick präziser ab, weil es den unmöglichen
Fall „leeres Label“ ausschließt. Praktisch matchen beide reale Hosts gleich.

Noch ein Detail, das gelegentlich beißt: .* und .+ sind gierig (greedy), sie
nehmen so viel wie möglich. Beim Hostname-Matching ist das egal, beim Zerlegen längerer
Strings (z. B. URL-Pfade) kann es zu viel greifen. Wer dort nur bis zum nächsten
Trennzeichen will, nutzt eine Zeichenklasse wie [^/]+ statt .+.

Praxisbeispiel: Wildcard-Subdomain

Ziel: alle Subdomains von beispiel.com sollen einen Dienst nutzen dürfen – ein
typischer Fall etwa bei der aliasgroup-Allow-Liste von Collabora CODE, die als Regex
ausgewertet wird. Deshalb scheitert der naheliegende Glob-Versuch:

# FALSCH – Glob, kein Regex:
https://*.beispiel.com
https://*\.beispiel.com     # Escapen hilft nichts, das führende * bleibt das Problem

# Regex-Wildcard (Grundidee):
https://.*\.beispiel\.com

Der einzige Unterschied zwischen Glob und Regex ist ein Punkt vor dem Stern:
* wird zu .*.

Zerlegt:

https://    .*          \.         beispiel    \.    com
  Text   irgendwas   echter Pkt      Text     Pkt    Text

Also: „https://, dann beliebige Zeichen (die Subdomain), dann ein echter Punkt,
dann beispiel.com„. Diese Grundidee stimmt – aber sie ist noch nicht sicher. Warum,
zeigt der nächste Abschnitt.

Sicherheit: der Trennpunkt ist eine Grenze, keine Kosmetik

Ein verlockender, aber gefährlicher Kurzschluss ist, den Trennpunkt wegzulassen, um
„Domain und Subdomain auf einmal“ zu erschlagen:

# RISKANT:
https://.*beispiel\.com

Das matcht alles, das auf beispiel.com endet – also auch
angreiferbeispiel.com. Wer sich eine passend benannte Domain registriert, kommt
durch die Allow-Liste. Bei kurzen oder gängigen Domain-Stämmen ist die
Kollisionsgefahr real.

Genauso wichtig: verlass dich nie auf die implizite Verankerung des Werkzeugs.
Manche Engines prüfen das Muster gegen die ganze Zeichenkette (fullmatch), andere
suchen es nur irgendwo im String (search). Im zweiten Fall ist selbst
.*\.beispiel\.com angreifbar, etwa über x.beispiel.com.angreifer.com – das Muster
findet sich ja als Teilstring wieder. Welches Verhalten ein konkretes Tool zeigt, ist
oft nicht dokumentiert. Die robuste Antwort ist, selbst zu verankern, statt es zu
hoffen.

Wer Apex (nackte Domain) und alle Subdomains sicher abdecken will, macht das
Label samt Punkt optional, setzt den Punkt als harte Grenze und verankert das Muster
an beiden Enden:

^https://(.+\.)?beispiel\.com$
  • ^ und $ = Anfang und Ende fest verankert, nichts lässt sich davor oder dahinter anhängen
  • (.+\.)? = entweder nichts, oder „mindestens ein Zeichen + echter Punkt“
  • dann die exakte Domain

Ergebnis:

  • https://beispiel.com (Apex) → trifft
  • https://kunde1.beispiel.com → trifft
  • https://angreiferbeispiel.com → trifft nicht (zwischen „angreifer“ und „beispiel“
    fehlt der Punkt)
  • https://x.beispiel.com.angreifer.com → trifft nicht (durch $ am Ende)

Optionale Verschärfung: Zeichensatz eingrenzen statt .+, damit nur gültige
Hostnamen-Zeichen durchkommen:

^https://([a-z0-9-]+\.)?beispiel\.com$

Testen statt raten

Regex liest sich schnell falsch. Statt ein Muster live in einer Produktiv-Config
auszuprobieren, gehört es vorher in einen Tester. regex101.com
zeigt für jedes Zeichen an, was es tut, und markiert, welcher Teil eines Beispiel-Hosts
warum matcht. Gerade beim Verankern und bei Zeichenklassen erspart das viel Fehlersuche.

Ein Hinweis zu Dialekten: Regex ist nicht überall identisch (PCRE, POSIX, RE2, …).
Die hier gezeigten Grundzeichen funktionieren in allen gängigen Engines gleich, bei
exotischeren Konstrukten lohnt der Blick in die Doku des jeweiligen Werkzeugs.

Quintessenz

Drei Sätze, die die meisten Fehler verhindern:

  1. * bezieht sich auf das Zeichen davor. Für eine Wildcard braucht es erst ein
    „beliebiges Zeichen“ (.) und dann „beliebig oft“ (*), zusammen .*.
  2. Escapt wird nur, was wörtlich gemeint ist – die echten Trennpunkte (\.),
    nie der *.
  3. Der Trennpunkt ist eine Sicherheitsgrenze, Verankerung der Schutzzaun. Ohne
    beides matcht das Muster fremde Domains, die nur zufällig auf denselben Namen enden.

Kommentar hinterlassen

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert