Reguläre Ausdrücke gehören zu den mächtigsten Werkzeugen in der Textverarbeitung. Mit ihnen lassen sich komplexe Suchmuster definieren, Eingaben validieren und Zeichenketten gezielt transformieren. PHP bietet dafür die PCRE-Bibliothek (Perl Compatible Regular Expressions), die eine umfangreiche und performante Regex-Engine bereitstellt. In diesem Tutorial lernst du die Grundlagen regulärer Ausdrücke kennen, verstehst die wichtigsten Bausteine und wendest sie mit den PHP-Funktionen preg_match(), preg_match_all() und preg_replace() in der Praxis an.

Der Einstieg beginnt mit der Frage, was reguläre Ausdrücke überhaupt sind und wofür sie sich besonders gut eignen.
Was sind reguläre Ausdrücke?
Ein regulärer Ausdruck (englisch: Regular Expression, kurz Regex) ist ein Muster, das eine bestimmte Menge von Zeichenketten beschreibt. Anstatt nach einem festen Wort zu suchen, definiert ein Regex eine Regel, der ein String entsprechen muss. So lässt sich beispielsweise prüfen, ob eine Eingabe dem Format einer E-Mail-Adresse, einer Postleitzahl oder einer Telefonnummer entspricht.
Reguläre Ausdrücke werden in vielen Programmiersprachen unterstützt. Die Syntax ist weitgehend einheitlich, sodass Regex-Kenntnisse aus PHP auch in JavaScript, Python oder anderen Sprachen anwendbar sind. Der entscheidende Vorteil gegenüber einfachen String-Funktionen wie str_contains() oder strpos() liegt in der Flexibilität: Mit einem einzigen Muster lassen sich zahlreiche Varianten einer Zeichenkette erfassen.
PCRE in PHP
PHP verwendet intern die PCRE-Bibliothek, die eine vollständige Implementierung der Perl-kompatiblen regulären Ausdrücke bereitstellt. Alle modernen PHP-Regex-Funktionen beginnen mit dem Präfix preg_ und nutzen diese Bibliothek. Ältere Funktionen mit dem Präfix ereg_ sind seit PHP 7.0 entfernt und sollten nicht mehr verwendet werden.
Ein PCRE-Muster wird in PHP als String übergeben und muss von Delimitern umschlossen sein. Der am häufigsten verwendete Delimiter ist der Schrägstrich /. Nach dem schließenden Delimiter können optionale Modifier folgen, die das Verhalten der Suche beeinflussen.
<?php
/* Grundstruktur eines Regex-Musters */
$pattern = '/muster/i';
/* Delimiter: /
Muster: muster
Modifier: i (case-insensitive) */
Als Delimiter eignet sich jedes nicht-alphanumerische Zeichen. Wenn das Muster selbst viele Schrägstriche enthält, bieten sich alternative Delimiter wie # oder ~ an, um das Escapen zu vermeiden.
Die Grundbausteine eines Regex
Jeder reguläre Ausdruck setzt sich aus verschiedenen Bausteinen zusammen. Das Verständnis dieser Bausteine ist die Grundlage für das Erstellen eigener Muster.
Literale Zeichen
Literale Zeichen sind die einfachste Form eines Regex. Sie stehen für sich selbst und stimmen genau mit dem jeweiligen Zeichen im Suchtext überein. Der Ausdruck /hallo/ findet die Zeichenkette "hallo" im durchsuchten String.
<?php
$text = 'Hallo Welt, hallo PHP!';
/* Suche nach dem literalen Wort "hallo" */
$treffer = preg_match('/hallo/', $text, $matches);
echo $treffer; /* Ausgabe: 1 */
echo $matches[0]; /* Ausgabe: hallo */
Meta-Zeichen und ihre Bedeutung
Meta-Zeichen haben in regulären Ausdrücken eine besondere Bedeutung und stehen nicht für sich selbst. Die folgenden Zeichen sind Meta-Zeichen: . ^ $ * + ? { } [ ] \ | ( ). Um ein Meta-Zeichen als literales Zeichen zu verwenden, muss es mit einem Backslash \ escaped werden.
Der Punkt . ist eines der wichtigsten Meta-Zeichen. Er steht für ein beliebiges einzelnes Zeichen (außer dem Zeilenumbruch, sofern der Modifier s nicht gesetzt ist). Das Pipe-Zeichen | fungiert als logisches Oder und ermöglicht Alternativen innerhalb eines Musters.
Zeichenklassen (Character Classes)
Zeichenklassen werden in eckige Klammern geschrieben und definieren eine Menge von Zeichen, von denen genau eines an der jeweiligen Position stehen darf. Der Ausdruck [aeiou] passt auf einen beliebigen Kleinbuchstaben-Vokal. Mit einem Bindestrich lässt sich ein Bereich angeben: [a-z] umfasst alle Kleinbuchstaben, [0-9] alle Ziffern.
Ein Zirkumflex ^ am Anfang einer Zeichenklasse negiert diese. Der Ausdruck [^0-9] passt auf jedes Zeichen, das keine Ziffer ist.
<?php
$plz = '10115';
/* Pruefe ob der String nur aus 5 Ziffern besteht */
if (preg_match('/^[0-9]{5}$/', $plz)) {
echo 'Gueltige deutsche Postleitzahl';
}
/* Finde alle Vokale in einem Text */
$text = 'Regulaere Ausdruecke';
preg_match_all('/[aeiouAEIOU]/', $text, $vokale);
echo implode(', ', $vokale[0]);
/* Ausgabe: e, u, a, e, e, A, u, u, e, e */
Vordefinierte Zeichenklassen (\d, \w, \s)
Für häufig benötigte Zeichenklassen stellt PCRE vordefinierte Abkürzungen bereit. Diese Kurzschreibweisen machen Muster kompakter und besser lesbar.
\d steht für eine Ziffer und entspricht [0-9]. \w steht für ein Wortzeichen und entspricht [a-zA-Z0-9_]. \s steht für ein Whitespace-Zeichen und umfasst Leerzeichen, Tabulator, Zeilenumbruch und ähnliche Zeichen. Die Großbuchstaben-Varianten \D, \W und \S sind jeweils die Negation: \D passt auf alles, was keine Ziffer ist.
Quantoren: Wie oft darf ein Zeichen vorkommen?
Quantoren legen fest, wie oft das vorangehende Element im Suchtext vorkommen darf. Ohne Quantor muss ein Element genau einmal auftreten. Mit Quantoren lassen sich optionale, wiederholte oder variable Vorkommen definieren.
* + ? und ihre Bedeutung
Die drei grundlegenden Quantoren sind der Stern *, das Plus + und das Fragezeichen ?. Der Stern bedeutet "null oder mehr Wiederholungen", das Plus bedeutet "eine oder mehr Wiederholungen" und das Fragezeichen bedeutet "null oder eine Wiederholung". Der Ausdruck \d+ passt demnach auf eine oder mehrere aufeinanderfolgende Ziffern.
Genaue Anzahl mit {n,m}
Für eine präzisere Steuerung der Wiederholungen dienen geschweifte Klammern. {3} bedeutet genau drei Wiederholungen, {2,5} bedeutet mindestens zwei und höchstens fünf Wiederholungen, und {3,} bedeutet mindestens drei Wiederholungen ohne Obergrenze.
Greedy vs. Lazy Matching
Standardmäßig arbeiten Quantoren greedy (gierig): Sie erfassen so viele Zeichen wie möglich. Durch Anhängen eines Fragezeichens an den Quantor wird er lazy (faul) und erfasst so wenige Zeichen wie möglich. Der Unterschied wird besonders beim Extrahieren von Inhalten aus umschließenden Zeichen deutlich.
<?php
$html = '<b>Fett</b> und <b>Wichtig</b>';
/* Greedy: erfasst alles von erstem <b> bis letztem </b> */
preg_match('/<b>.*<\/b>/', $html, $greedy);
echo $greedy[0];
/* Ausgabe: <b>Fett</b> und <b>Wichtig</b> */
/* Lazy: erfasst so wenig wie moeglich */
preg_match('/<b>.*?<\/b>/', $html, $lazy);
echo $lazy[0];
/* Ausgabe: <b>Fett</b> */
Anker: Position im String festlegen
Anker prüfen keine Zeichen, sondern Positionen innerhalb des Strings. Der Zirkumflex ^ verankert das Muster am Anfang des Strings, das Dollarzeichen $ am Ende. Die Kombination ^...$ stellt sicher, dass der gesamte String dem Muster entsprechen muss, nicht nur ein Teilabschnitt.
Der Anker \b markiert eine Wortgrenze. Damit lässt sich sicherstellen, dass ein Muster nur als eigenständiges Wort gefunden wird und nicht als Teil eines längeren Wortes. Der Ausdruck /\bPHP\b/ findet "PHP" als einzelnes Wort, aber nicht das "PHP" in "PHPUnit".
flowchart TB
D["Anfang des Strings"] -.-> A["^"]
A --- B["Muster"]
B --- C["$"]
C -.-> E["Ende des Strings"]
F["\b"] --- G["Wort"]
G --- H["\b"]
F -.-> I["Wortgrenze links"]
H -.-> J["Wortgrenze rechts"]
Gruppen und Captures
Gruppen fassen Teile eines Musters zusammen und ermöglichen es, auf die gefundenen Teilabschnitte einzeln zuzugreifen. Sie sind ein zentrales Konzept für die Arbeit mit regulären Ausdrücken in PHP.
Runde Klammern für Gruppen
Runde Klammern () erzeugen eine sogenannte Capture Group. Der Inhalt, der von der Gruppe erfasst wird, steht nach dem Match im Ergebnis-Array zur Verfügung. Die erste Gruppe ist über Index 1 erreichbar, die zweite über Index 2 und so weiter. Der Index 0 enthält immer den gesamten Treffer.
<?php
$datum = 'Heute ist der 06.03.2026';
/* Gruppen fuer Tag, Monat und Jahr */
$pattern = '/(\d{2})\.(\d{2})\.(\d{4})/';
if (preg_match($pattern, $datum, $matches)) {
echo 'Gesamter Treffer: ' . $matches[0]; /* 06.03.2026 */
echo 'Tag: ' . $matches[1]; /* 06 */
echo 'Monat: ' . $matches[2]; /* 03 */
echo 'Jahr: ' . $matches[3]; /* 2026 */
}
Benannte Gruppen
Anstelle von numerischen Indizes können Gruppen auch benannt werden. Die Syntax dafür lautet (?P<name>...) oder (?<name>...). Benannte Gruppen erhöhen die Lesbarkeit des Codes erheblich, da der Zugriff über sprechende Bezeichner statt über Zahlen erfolgt.
<?php
$log = '[2026-03-06 14:30:00] ERROR: Datei nicht gefunden';
$pattern = '/\[(?P<datum>[\d-]+)\s(?P<zeit>[\d:]+)\]\s(?P<level>\w+):\s(?P<nachricht>.+)/';
if (preg_match($pattern, $log, $matches)) {
echo $matches['datum']; /* 2026-03-06 */
echo $matches['level']; /* ERROR */
echo $matches['nachricht']; /* Datei nicht gefunden */
}
Non-Capturing Groups (?:)
Nicht jede Gruppe muss ihren Inhalt erfassen. Wenn eine Gruppierung nur für die logische Strukturierung des Musters benötigt wird, eignet sich eine Non-Capturing Group mit der Syntax (?:...). Sie fasst Teile des Musters zusammen, erzeugt aber keinen Eintrag im Ergebnis-Array. Das ist effizienter und hält die Captures übersichtlich.
Modifier (Pattern-Modifikatoren)
Modifier werden nach dem schließenden Delimiter angefügt und verändern das Verhalten des gesamten Musters. Die wichtigsten Modifier in PHP sind:
i macht die Suche case-insensitive, sodass Groß- und Kleinschreibung keine Rolle spielt. m aktiviert den Multiline-Modus, in dem ^ und $ nicht nur auf den Anfang und das Ende des gesamten Strings passen, sondern auch auf den Anfang und das Ende jeder einzelnen Zeile. s bewirkt, dass der Punkt . auch Zeilenumbrüche erfasst. u aktiviert die UTF-8-Unterstützung, die für die korrekte Verarbeitung von Umlauten und anderen Nicht-ASCII-Zeichen unverzichtbar ist.
Die wichtigsten PHP-Regex-Funktionen
PHP stellt mehrere Funktionen für die Arbeit mit regulären Ausdrücken bereit. Die drei am häufigsten verwendeten sind preg_match(), preg_match_all() und preg_replace().
preg_match() für einen Treffer
Die Funktion preg_match() durchsucht einen String nach dem ersten Vorkommen eines Musters. Sie gibt 1 zurück, wenn ein Treffer gefunden wurde, 0 wenn kein Treffer vorliegt, und false im Fehlerfall. Das optionale dritte Argument nimmt ein Array entgegen, das die gefundenen Treffer und Captures enthält.
<?php
$email = 'kontakt@beispiel.de';
/* Einfache E-Mail-Validierung */
$pattern = '/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/';
if (preg_match($pattern, $email)) {
echo 'Gueltige E-Mail-Adresse';
} else {
echo 'Ungueltige E-Mail-Adresse';
}
preg_match_all() für alle Treffer
Während preg_match() nach dem ersten Treffer stoppt, findet preg_match_all() alle Vorkommen des Musters im String. Die Funktion gibt die Anzahl der Treffer zurück. Das Ergebnis-Array enthält alle gefundenen Übereinstimmungen und deren Capture Groups.
<?php
$text = 'Preise: 19,99 EUR, 5,50 EUR und 149,00 EUR';
/* Alle Preise im Text finden */
$pattern = '/(\d+,\d{2})\sEUR/';
$anzahl = preg_match_all($pattern, $text, $matches);
echo 'Gefundene Preise: ' . $anzahl; /* 3 */
foreach ($matches[1] as $preis) {
echo $preis . ' EUR';
}
/* 19,99 EUR */
/* 5,50 EUR */
/* 149,00 EUR */
preg_replace() für Suchen und Ersetzen
Die Funktion preg_replace() sucht nach einem Muster und ersetzt alle Treffer durch einen angegebenen Ersetzungsstring. In der Ersetzung kann mit $1, $2 usw. auf die Captures der Gruppen zugegriffen werden. Das macht gezielte Transformationen von Textinhalten möglich.
<?php
$text = 'Kontakt: 0170-1234567 oder 0171-9876543';
/* Telefonnummern anonymisieren */
$anonymisiert = preg_replace('/(\d{4})-(\d+)/', '$1-XXXXXXX', $text);
echo $anonymisiert;
/* Ausgabe: Kontakt: 0170-XXXXXXX oder 0171-XXXXXXX */
/* Datumsformat umwandeln: DD.MM.YYYY zu YYYY-MM-DD */
$datum = '06.03.2026';
$iso = preg_replace('/(\d{2})\.(\d{2})\.(\d{4})/', '$3-$2-$1', $datum);
echo $iso;
/* Ausgabe: 2026-03-06 */
Praktische Beispiele
Die folgenden Beispiele zeigen typische Anwendungsfälle für reguläre Ausdrücke in der PHP-Entwicklung. Sie verdeutlichen, wie sich die einzelnen Bausteine zu nützlichen Mustern kombinieren lassen.
<?php
/* Passwort-Validierung:
mindestens 8 Zeichen, ein Grossbuchstabe,
ein Kleinbuchstabe, eine Ziffer */
function validierePasswort(string $passwort): bool
{
$pattern = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/';
return (bool) preg_match($pattern, $passwort);
}
echo validierePasswort('Sicher123'); /* true */
echo validierePasswort('kurz1'); /* false */
/* Hashtags aus einem Social-Media-Text extrahieren */
$post = 'Neues Projekt gestartet! #PHP #Regex #WebDev';
preg_match_all('/#(\w+)/u', $post, $tags);
echo implode(', ', $tags[1]);
/* Ausgabe: PHP, Regex, WebDev */
/* URL-Slug erzeugen: Sonderzeichen entfernen, Leerzeichen ersetzen */
function erzeugeSlug(string $titel): string
{
$slug = mb_strtolower($titel);
$slug = preg_replace('/[^a-z0-9\s\-]/', '', $slug);
$slug = preg_replace('/[\s]+/', '-', $slug);
return trim($slug, '-');
}
echo erzeugeSlug('PHP Regex: Ein Tutorial!');
/* Ausgabe: php-regex-ein-tutorial */
/* Sonderzeichen fuer Regex escapen mit preg_quote() */
$benutzereingabe = 'Preis: 9.99$';
$escaped = preg_quote($benutzereingabe, '/');
echo $escaped;
/* Ausgabe: Preis\:\ 9\.99\$ */
Die Funktion preg_quote() ist besonders wichtig, wenn Benutzereingaben in ein Regex-Muster eingebaut werden. Sie stellt sicher, dass Meta-Zeichen in der Eingabe als literale Zeichen behandelt werden und keine unbeabsichtigte Wirkung entfalten.
Häufige Fehler und Tipps
Beim Arbeiten mit regulären Ausdrücken treten einige Fehler immer wieder auf. Die folgenden Hinweise helfen, typische Stolperfallen zu vermeiden.
Das Vergessen der Delimiter ist einer der häufigsten Fehler. Jedes Muster muss in PHP von Delimitern umschlossen sein. Ohne Delimiter gibt preg_match() eine Warnung aus und liefert false zurück.
Ein weiterer häufiger Fehler ist das fehlende Escapen von Meta-Zeichen. Ein Punkt in einem Muster passt auf jedes beliebige Zeichen. Wenn ein literaler Punkt gesucht wird, muss er als \. geschrieben werden. Gleiches gilt für andere Meta-Zeichen wie $, * oder (.
Bei der Verarbeitung von deutschen Texten mit Umlauten sollte immer der Modifier u verwendet werden. Ohne UTF-8-Modus können Umlaute und andere Multibyte-Zeichen zu unerwarteten Ergebnissen führen, da PCRE sie sonst als einzelne Bytes statt als zusammengehörige Zeichen behandelt.
Die Rückgabewerte von preg_match() sollten stets korrekt geprüft werden. Da die Funktion false im Fehlerfall zurückgibt, empfiehlt sich der strikte Vergleich === 1 oder === 0, um Fehler von einem fehlenden Treffer unterscheiden zu können.
Komplexität sollte schrittweise aufgebaut werden. Es empfiehlt sich, ein Muster zunächst einfach zu beginnen und dann Schritt für Schritt zu erweitern. Online-Tools wie regex101.com bieten eine interaktive Umgebung, in der sich Muster testen und debuggen lassen. Dort wird auch angezeigt, welche Teile des Musters auf welche Abschnitte des Textes passen.
Performanz ist ein weiterer Aspekt. Übermäßig komplexe Muster mit vielen verschachtelten Quantoren können zu einem sogenannten Catastrophic Backtracking führen, bei dem die Regex-Engine extrem lange für die Auswertung braucht. Das lässt sich vermeiden, indem Muster so spezifisch wie möglich formuliert werden und possessive Quantoren oder atomare Gruppen eingesetzt werden, wo es sinnvoll ist.
Fazit
Reguläre Ausdrücke sind ein unverzichtbares Werkzeug in der PHP-Entwicklung. Mit den Funktionen preg_match(), preg_match_all() und preg_replace() deckt PHP die wichtigsten Anwendungsfälle ab: vom einfachen Prüfen eines Musters über das Extrahieren aller Treffer bis hin zum gezielten Ersetzen von Textabschnitten. Die Grundbausteine aus Zeichenklassen, Quantoren, Ankern und Gruppen lassen sich flexibel kombinieren, um auch komplexe Suchmuster präzise zu formulieren. Wer die Syntax einmal verstanden hat, profitiert in vielen Bereichen der Webentwicklung davon, sei es bei der Validierung von Formulareingaben, beim Parsen von Log-Dateien oder bei der Transformation von Datenformaten. Der Schlüssel liegt darin, mit einfachen Mustern zu beginnen und die Komplexität schrittweise zu steigern.