Die Funktion preg_replace() ist eines der mächtigsten Werkzeuge in PHP, wenn es darum geht, Zeichenketten anhand von Mustern zu durchsuchen und gezielt zu ersetzen. Während str_replace() nur feste Zeichenketten ersetzen kann, arbeitet preg_replace() mit regulären Ausdrücken und ermöglicht dadurch flexible Muster, Rückverweise und komplexe Transformationen. In diesem Tutorial lernst du die Syntax und alle Parameter von preg_replace() kennen, siehst praktische Beispiele und erfährst, wann du besser zu str_replace() oder preg_replace_callback() greifst.

Los geht es mit der grundlegenden Arbeitsweise der Funktion und einem ersten Codebeispiel.
Was macht preg_replace()?
Die Funktion preg_replace() durchsucht einen String oder ein Array von Strings nach einem regulären Ausdruck und ersetzt alle Treffer durch einen angegebenen Ersetzungstext. Standardmäßig werden dabei alle Vorkommen des Musters ersetzt, nicht nur das erste. Der Rückgabewert ist der modifizierte String beziehungsweise das modifizierte Array. Tritt ein Fehler auf, etwa durch ein ungültiges Pattern, gibt die Funktion null zurück.
<?php
$text = 'Heute ist der 06.03.2026';
/* Alle Ziffern durch ein Rautezeichen ersetzen */
$ergebnis = preg_replace('/[0-9]/', '#', $text);
echo $ergebnis;
/* Ausgabe: Heute ist der ##.##.#### */
In diesem Beispiel wird jede einzelne Ziffer im String durch ein Rautezeichen ersetzt. Das Muster /[0-9]/ passt auf jede Ziffer von 0 bis 9. Da preg_replace() standardmäßig alle Treffer ersetzt, werden sämtliche Ziffern im String ausgetauscht.
Die Parameter im Detail
Die vollständige Signatur von preg_replace() umfasst fünf Parameter. Die ersten drei sind Pflichtparameter, die letzten beiden sind optional und bieten zusätzliche Kontrolle über das Verhalten der Funktion.
preg_replace(
string|array $pattern,
string|array $replacement,
string|array $subject,
int $limit = -1,
int &$count = null
): string|array|null
Pattern (Suchmuster)
Der erste Parameter ist das Suchmuster als regulärer Ausdruck. Das Pattern muss in Trennzeichen eingeschlossen sein, üblicherweise Schrägstriche. Innerhalb des Musters können alle PCRE-Ausdrücke verwendet werden, darunter Zeichenklassen, Quantifizierer, Gruppen und Anker. Es ist auch möglich, ein Array von Patterns zu übergeben, um mehrere Muster in einem Aufruf zu ersetzen.
Replacement (Ersetzungstext)
Der zweite Parameter ist der Ersetzungstext, der an die Stelle jedes Treffers tritt. Im Replacement können Rückverweise wie $1 oder 1 verwendet werden, um auf eingefangene Gruppen aus dem Pattern zuzugreifen. Wird ein Array von Patterns übergeben, kann auch ein Array von Replacements angegeben werden, wobei jedes Pattern dem Replacement mit dem gleichen Index zugeordnet wird.
Subject (Eingabestring oder Array)
Der dritte Parameter ist der Eingabestring, in dem gesucht und ersetzt wird. Wird anstelle eines Strings ein Array übergeben, wendet preg_replace() die Ersetzung auf jedes Element des Arrays an und gibt ein Array zurück. Das ist besonders nützlich, wenn mehrere Strings gleichzeitig verarbeitet werden sollen.
Limit (maximale Ersetzungen)
Der vierte Parameter begrenzt die Anzahl der Ersetzungen pro Muster und Subject-String. Der Standardwert ist -1, was bedeutet, dass alle Vorkommen ersetzt werden. Ein Wert von 1 ersetzt nur das erste Vorkommen, ein Wert von 3 die ersten drei Vorkommen.
<?php
$text = 'Apfel, Birne, Apfel, Kirsche, Apfel';
/* Nur das erste Vorkommen von Apfel ersetzen */
$ergebnis = preg_replace('/Apfel/', 'Orange', $text, 1);
echo $ergebnis;
/* Ausgabe: Orange, Birne, Apfel, Kirsche, Apfel */
Count (Zähler)
Der fünfte Parameter ist eine Referenzvariable, in der preg_replace() die Anzahl der tatsächlich durchgeführten Ersetzungen speichert. Dieser Zähler ist hilfreich, wenn im Nachgang geprüft werden soll, ob und wie viele Ersetzungen stattgefunden haben.
<?php
$text = 'PHP ist toll. PHP ist schnell. PHP ist stabil.';
$anzahl = 0;
$ergebnis = preg_replace('/PHP/', 'Python', $text, -1, $anzahl);
echo $ergebnis;
/* Ausgabe: Python ist toll. Python ist schnell. Python ist stabil. */
echo "Ersetzungen: $anzahl";
/* Ausgabe: Ersetzungen: 3 */
Der Wert -1 für den Limit-Parameter sorgt dafür, dass alle Vorkommen ersetzt werden. Die Variable $anzahl enthält nach dem Aufruf den Wert 3, da drei Ersetzungen durchgeführt wurden.
Rückverweise im Ersetzungstext
Rückverweise ermöglichen es, Teile des gefundenen Textes im Ersetzungstext wiederzuverwenden. Jede Gruppe im Pattern, die in runde Klammern eingeschlossen ist, kann im Replacement über $1, $2 und so weiter referenziert werden. Die Schreibweise 1 ist dann nötig, wenn direkt nach dem Rückverweis eine Ziffer folgt, die nicht zum Index gehört. Der Rückverweis $0 steht für den gesamten Treffer.
<?php
$text = 'Mein Geburtstag ist am 15.07.1990';
/* Datum von DD.MM.YYYY in YYYY-MM-DD umwandeln */
$ergebnis = preg_replace(
'/(\d{2})\.(\d{2})\.(\d{4})/',
'$3-$2-$1',
$text
);
echo $ergebnis;
/* Ausgabe: Mein Geburtstag ist am 1990-07-15 */
In diesem Beispiel fangen drei Gruppen den Tag, den Monat und das Jahr ein. Im Ersetzungstext werden die Gruppen in der Reihenfolge Jahr, Monat, Tag zusammengesetzt. So wird das deutsche Datumsformat in das ISO-Format umgewandelt. Rückverweise sind besonders wertvoll, wenn die gefundenen Inhalte nicht verworfen, sondern umstrukturiert werden sollen.
flowchart TD
A["preg_replace aufrufen"] --> B{"Pattern gültig?"}
B -->|Nein| C["null zurückgeben"]
B -->|Ja| D["Subject durchsuchen"]
D --> E{"Treffer gefunden?"}
E -->|Nein| F["Original zurückgeben"]
E -->|Ja| G["Gruppen erfassen"]
G --> H["Rückverweise einsetzen"]
H --> I{"Limit erreicht?"}
I -->|Nein| D
I -->|Ja| J["Ergebnis zurückgeben"]
Mehrere Muster gleichzeitig ersetzen
Werden Arrays für Pattern und Replacement übergeben, verarbeitet preg_replace() die Muster der Reihe nach. Das erste Pattern wird durch das erste Replacement ersetzt, das zweite Pattern durch das zweite Replacement und so weiter. Enthält das Pattern-Array mehr Einträge als das Replacement-Array, wird für die übrigen Patterns ein leerer String als Ersetzung verwendet.
<?php
$text = '<b>Fetter Text</b> und <i>kursiver Text</i>';
$patterns = [
'/<b>(.*?)<\/b>/',
'/<i>(.*?)<\/i>/'
];
$replacements = [
'<strong>$1</strong>',
'<em>$1</em>'
];
$ergebnis = preg_replace($patterns, $replacements, $text);
echo $ergebnis;
/* Ausgabe: <strong>Fetter Text</strong> und <em>kursiver Text</em> */
Dieses Beispiel wandelt veraltete HTML-Tags in ihre semantischen Entsprechungen um. Das Pattern <b> wird durch <strong> ersetzt, <i> durch <em>. Durch die Rückverweise bleibt der Inhalt zwischen den Tags erhalten. Die Reihenfolge der Arrays ist entscheidend, da die Zuordnung über den Index erfolgt.
Modifier: Case-Insensitive und Multiline
Modifier werden nach dem abschließenden Trennzeichen des Patterns angegeben und verändern das Verhalten des regulären Ausdrucks. Der Modifier i macht die Suche case-insensitive, sodass Groß- und Kleinschreibung ignoriert werden. Der Modifier m aktiviert den Multiline-Modus, in dem die Anker ^ und $ nicht nur auf den Anfang und das Ende des gesamten Strings, sondern auf den Anfang und das Ende jeder Zeile passen. Der Modifier s sorgt dafür, dass der Punkt auch Zeilenumbruchzeichen erfasst. Mehrere Modifier lassen sich kombinieren, etwa /muster/im für case-insensitive und multiline gleichzeitig.
<?php
$text = 'PHP ist beliebt. php ist vielseitig. Php ist stabil.';
/* Case-insensitive Ersetzung mit dem Modifier i */
$ergebnis = preg_replace('/php/i', 'JavaScript', $text);
echo $ergebnis;
/* Ausgabe: JavaScript ist beliebt. JavaScript ist vielseitig. JavaScript ist stabil. */
Ohne den Modifier i würde nur das kleingeschriebene php im zweiten Satz ersetzt werden. Mit dem Modifier werden alle drei Varianten erkannt und ersetzt, unabhängig von der Schreibweise.
preg_replace vs. str_replace
Die Funktion str_replace() ersetzt feste Zeichenketten und benötigt keine regulären Ausdrücke. Sie ist deutlich schneller als preg_replace(), da der Overhead der Regex-Engine entfällt. Wenn das Suchmuster eine feste Zeichenkette ist und keine Mustererkennung benötigt wird, sollte immer str_replace() bevorzugt werden. preg_replace() ist dann die richtige Wahl, wenn das Suchmuster variabel ist, Zeichenklassen, Quantifizierer oder Gruppen enthält oder wenn Rückverweise im Ersetzungstext benötigt werden.
Ein typisches Beispiel: Das Entfernen aller aufeinanderfolgenden Leerzeichen kann mit str_replace() nicht in einem einzigen Aufruf gelöst werden, da die Anzahl der Leerzeichen variiert. Mit preg_replace('/\s+/', ' ', $text) ist das Problem in einer Zeile gelöst. Geht es hingegen nur darum, ein bestimmtes Wort durch ein anderes zu ersetzen, ist str_replace('alt', 'neu', $text) die performantere Lösung.
preg_replace vs. preg_replace_callback
Die Funktion preg_replace_callback() ist die erweiterte Variante von preg_replace(). Anstelle eines festen Ersetzungstextes nimmt sie eine Callback-Funktion entgegen, die für jeden Treffer aufgerufen wird. Der Callback erhält ein Array mit dem gesamten Treffer und allen Gruppen als Parameter und gibt den Ersetzungstext zurück.
<?php
$text = 'produkt-123 und produkt-456';
/* Produktnummern verdoppeln mit preg_replace_callback */
$ergebnis = preg_replace_callback(
'/produkt-(\d+)/',
function ($treffer) {
$nummer = (int) $treffer[1];
return 'produkt-' . ($nummer * 2);
},
$text
);
echo $ergebnis;
/* Ausgabe: produkt-246 und produkt-912 */
Der entscheidende Unterschied: preg_replace() erlaubt im Ersetzungstext nur Rückverweise und statischen Text. Sobald der Ersetzungstext von einer Berechnung, einer Datenbankabfrage oder einer anderen dynamischen Logik abhängt, ist preg_replace_callback() die richtige Wahl. Für einfache Ersetzungen ohne Logik bleibt preg_replace() die schlankere und lesbarere Lösung.
Praktische Beispiele
Die folgenden Beispiele zeigen typische Anwendungsfälle, die in der Praxis häufig vorkommen. Sie decken die Bereinigung von Benutzereingaben, die Umformatierung von Text und das Entfernen unerwünschter Zeichen ab.
<?php
/* Beispiel 1: Mehrfache Leerzeichen auf eines reduzieren */
$text = 'Zu viele Leerzeichen hier';
$bereinigt = preg_replace('/\s+/', ' ', $text);
echo $bereinigt;
/* Ausgabe: Zu viele Leerzeichen hier */
/* Beispiel 2: HTML-Tags komplett entfernen */
$html = '<p>Ein <strong>wichtiger</strong> Absatz</p>';
$plain = preg_replace('/<[^>]+>/', '', $html);
echo $plain;
/* Ausgabe: Ein wichtiger Absatz */
/* Beispiel 3: Telefonnummer formatieren */
$telefon = '0176 12345678';
$formatiert = preg_replace('/(\d{4})\s*(\d{8})/', '$1 $2', $telefon);
echo $formatiert;
/* Ausgabe: 0176 12345678 */
/* Beispiel 4: E-Mail-Adressen in einem Text maskieren */
$text = 'Schreib an info@example.com oder an admin@example.org';
$maskiert = preg_replace('/([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)/', '***@$2', $text);
echo $maskiert;
/* Ausgabe: Schreib an ***@example.com oder an ***@example.org */
/* Beispiel 5: CamelCase in Woerter mit Leerzeichen umwandeln */
$camel = 'meinLangerVariablenName';
$lesbar = preg_replace('/([a-z])([A-Z])/', '$1 $2', $camel);
echo $lesbar;
/* Ausgabe: mein Langer Variablen Name */
Im ersten Beispiel wird das Muster \s+ verwendet, das auf ein oder mehrere Whitespace-Zeichen passt. Im zweiten Beispiel erkennt <[^>]+> jedes HTML-Tag und entfernt es. Das vierte Beispiel maskiert den lokalen Teil einer E-Mail-Adresse, indem die erste Gruppe durch Sternchen ersetzt wird, während die Domain über den Rückverweis $2 erhalten bleibt. Das fünfte Beispiel nutzt zwei Gruppen, um an der Grenze zwischen Klein- und Großbuchstaben ein Leerzeichen einzufügen.
Häufige Fehler und Tipps
Bei der Arbeit mit preg_replace() treten bestimmte Fehler immer wieder auf. Das Wissen um diese typischen Stolperfallen spart Zeit bei der Fehlersuche.
Der häufigste Fehler ist ein fehlendes Trennzeichen im Pattern. Jeder reguläre Ausdruck muss in Trennzeichen eingeschlossen sein, zum Beispiel /muster/ oder #muster#. Fehlen die Trennzeichen, gibt preg_replace() den Wert null zurück und erzeugt eine Warnung. Ein zweiter häufiger Fehler ist das Vergessen der Maskierung von Sonderzeichen. Zeichen wie der Punkt, das Fragezeichen oder die runde Klammer haben in regulären Ausdrücken eine besondere Bedeutung und müssen mit einem Backslash maskiert werden, wenn sie wörtlich gemeint sind. Die Funktion preg_quote() kann dabei helfen, einen String für die Verwendung in einem Pattern vorzubereiten.
Ein weiterer Fehler betrifft die Gierigkeit von Quantifizierern. Das Muster .* ist standardmäßig gierig und erfasst so viel Text wie möglich. In vielen Fällen ist das nicht gewünscht. Der Quantifizierer .*? ist hingegen genügsam und erfasst so wenig Text wie möglich. Besonders beim Arbeiten mit HTML-Tags oder geschachtelten Strukturen führt der gierige Modus oft zu unerwünschten Ergebnissen.
Es ist wichtig zu wissen, dass die veraltete Funktion ereg_replace() seit PHP 7.0 entfernt wurde. Sie gehörte zur alten POSIX-Regex-Erweiterung und wurde vollständig durch preg_replace() und die PCRE-Bibliothek abgelöst. Bestehender Code, der noch ereg_replace() verwendet, muss auf preg_replace() umgestellt werden.
Abschließend empfiehlt es sich, den Rückgabewert von preg_replace() immer auf null zu prüfen. Ein Rückgabewert von null deutet auf ein fehlerhaftes Pattern hin. Die Funktion preg_last_error() liefert in diesem Fall einen Fehlercode, der bei der Diagnose hilft. Seit PHP 8.0 gibt es zusätzlich preg_last_error_msg(), die eine lesbare Fehlermeldung zurückgibt.
Fazit
Die Funktion preg_replace() ist das zentrale Werkzeug in PHP für musterbasiertes Suchen und Ersetzen in Strings. Mit ihren fünf Parametern bietet sie volle Kontrolle über das Suchmuster, den Ersetzungstext, die Eingabe, die maximale Anzahl an Ersetzungen und einen Zähler für durchgeführte Ersetzungen. Rückverweise mit $1, $2 und 1 ermöglichen es, Teile des Treffers im Ersetzungstext wiederzuverwenden. Für einfache Zeichenkettenersetzungen ohne Muster ist str_replace() die schnellere Alternative. Sobald dynamische Logik im Ersetzungstext benötigt wird, ist preg_replace_callback() die bessere Wahl. Wer die typischen Fehlerquellen wie fehlende Trennzeichen, unmaskierte Sonderzeichen und gierige Quantifizierer kennt, kann preg_replace() sicher und effizient einsetzen.