preg_replace_callback
Die PHP-Funktion preg_replace_callback() führt eine Suche und Ersetzung per regulärem Ausdruck mit einer Callback-Funktion durch.
Einführung
preg_replace_callback() führt eine Suche und Ersetzung mit regulären Ausdrücken durch, jedoch wird anstelle eines festen Ersetzungsstrings eine Callback-Funktion übergeben, die für jede Übereinstimmung aufgerufen wird. Der Callback erhält die Übereinstimmung (und alle Capture-Gruppen) und gibt den einzusetzenden Text zurück. Dadurch können Ersetzungen mit echtem PHP-Code berechnet werden — ein Wort großschreiben, eine Zahl um 1 erhöhen, einen Wert in einer Tabelle nachschlagen — was die einfache Funktion preg_replace() nicht leisten kann.
Verwende diese Funktion immer dann, wenn die Ersetzung davon abhängt, was gefunden wurde. Ist die Ersetzung ein konstanter Text oder eine einfache Rückreferenz wie $1, bietet sich preg_replace() an; benötigst du pro Muster einen eigenen Callback, sieh dir preg_replace_callback_array() an.
Syntax
preg_replace_callback(
string|array $pattern,
callable $callback,
string|array $subject,
int $limit = -1,
int &$count = null,
int $flags = 0
): string|array|null| Parameter | Beschreibung |
|---|---|
$pattern | Der reguläre Ausdruck (ein begrenzter String) zum Abgleichen, oder ein Array von Mustern. |
$callback | Ein Callable, das für jede Übereinstimmung aufgerufen wird. Es erhält das Matches-Array und gibt den Ersetzungsstring zurück. |
$subject | Der String (oder das Array von Strings), der durchsucht und verändert werden soll. |
$limit | Maximale Anzahl von Ersetzungen pro Eingabe-String. -1 (Standardwert) bedeutet kein Limit. |
$count | Wird per Referenz übergeben; enthält nach dem Aufruf die Anzahl der vorgenommenen Ersetzungen. |
$flags | PREG_OFFSET_CAPTURE und/oder PREG_UNMATCHED_AS_NULL, analog zu preg_match(). |
Die Funktion gibt den geänderten String zurück oder null, wenn ein Regex-Fehler auftritt. Das erste Argument des Callbacks ist das $matches-Array: $matches[0] enthält die gesamte Übereinstimmung, $matches[1], $matches[2], … enthalten die erfassten Gruppen — genau wie das Array, das preg_match() befüllt.
Grundlegendes Beispiel: jedes Wort großschreiben
Das Muster \w+ trifft jede Folge von Wortzeichen. Für jede Übereinstimmung erhält der Callback $matches[0] (das Wort) und gibt dessen großgeschriebene Form zurück, die an der entsprechenden Stelle in den String eingefügt wird.
Arbeiten mit Capture-Gruppen
Klammern im Muster erzeugen Capture-Gruppen, die unter $matches[1], $matches[2] usw. verfügbar sind. Hier wird zu jeder Zahl in einem String 1 addiert:
<?php
$subject = 'Room 12, floor 3, building 7';
$result = preg_replace_callback('/(\d+)/', function ($m) {
return (string) ((int) $m[1] + 1);
}, $subject);
echo $result;
// Room 13, floor 4, building 8Da der Callback echten Code ausführt, wird der Inkrement pro Übereinstimmung berechnet — etwas, das ein statischer Ersetzungsstring niemals ausdrücken kann.
Ein praktischer Anwendungsfall: sensible Daten maskieren
Ein häufiger Einsatzzweck ist das teilweise Verbergen von E-Mail-Adressen oder Kartennummern in Logs. Der Callback kann entscheiden, wie viel von jeder Übereinstimmung sichtbar bleiben soll:
<?php
$text = 'Contact: [email protected] or [email protected]';
$result = preg_replace_callback('/([\w.]+)@([\w.]+)/', function ($m) {
$name = $m[1];
$masked = $name[0] . str_repeat('*', max(strlen($name) - 1, 1));
return $masked . '@' . $m[2];
}, $text);
echo $result;
// Contact: a****@example.com or b**@test.orgErsetzungen zählen und begrenzen
Die Parameter $limit und $count ermöglichen es, die Anzahl der verarbeiteten Übereinstimmungen zu begrenzen und zu erfahren, wie viele tatsächlich ersetzt wurden:
<?php
$subject = 'a a a a a';
$result = preg_replace_callback('/a/', function ($m) {
return 'b';
}, $subject, 2, $count);
echo $result, "\n"; // b b a a a
echo $count; // 2Nur die ersten beiden as werden ersetzt, weil $limit den Wert 2 hat, und $count gibt die Anzahl der vorgenommenen Ersetzungen aus.
preg_replace vs. preg_replace_callback
| Verwendung | Funktion |
|---|---|
Fester Text oder eine Rückreferenz wie $1 | preg_replace() |
| Ersetzung, die aus der Übereinstimmung berechnet wird | preg_replace_callback() |
| Ein eigener Callback pro Muster | preg_replace_callback_array() |
Zum Suchen ohne Ersetzen siehe preg_match() und preg_match_all(), sowie das Kapitel zu regulären Ausdrücken in PHP für die Mustersyntax.
Häufige Fallstricke
- Immer einen String zurückgeben. Der Rückgabewert des Callbacks wird als String behandelt und eingefügt.
nullzurückzugeben entfernt die Übereinstimmung; ein fehlendesreturnfügt einen leeren String ein. - Den richtigen Index verwenden.
$matches[0]ist die vollständige Übereinstimmung; Gruppe 1 liegt unter$matches[1]. Ein Off-by-One-Fehler hier ist der häufigste Bug. - Vorsicht beim Escaping. Anders als bei
preg_replace()werden im Ergebnis keine$1/\1-Rückreferenzen verwendet — der String wird selbst zusammengebaut, daher ist in der Ersetzung nichts zu escapen. - Ein
null-Rückgabewert der Funktion selbst (nicht des Callbacks) signalisiert einen Regex-Fehler, etwa einen nicht abgeschlossenen Begrenzer.
Fazit
preg_replace_callback() ist das richtige Werkzeug, wenn eine Ersetzung berechnet statt einfach angegeben werden muss. Es verbindet die Matching-Stärke regulärer Ausdrücke mit beliebigem PHP-Code im Callback und ist damit ideal zum Transformieren, Maskieren oder Neuberechnen von gefundenem Text. Für statische Ersetzungen bleibt preg_replace() die bessere Wahl, und für mehrere Muster gleichzeitig empfiehlt sich preg_replace_callback_array().