Reguläre Ausdrücke in PHP – benannte Gruppen statt $m[3]
Ein Treffer-Array aus Zahlen liest sich nach zwei Wochen wie eine Geheimschrift. Benannte Gruppen geben jedem Teil einen Namen – und preg_replace_callback ersetzt damit Dinge, die kein einfacher Ersetzungsstring kann.
Reguläre Ausdrücke haben einen schlechten Ruf, und meistens liegt es nicht am Muster, sondern am Ergebnis:
preg_match('/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/', $zeile, $m);
$monat = $m[2]; // welcher war noch mal der Monat?Sobald jemand vorne eine Gruppe einfügt, verschieben sich alle Nummern – und niemand merkt es, bis die Auswertung falsch ist.
Gruppen mit Namen
$muster = '/(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})[ T](?<stunde>\d{2}):(?<minute>\d{2})/';
if (preg_match($muster, $zeile, $m)) {
printf('%s.%s.%s um %s:%s Uhr', $m['tag'], $m['monat'], $m['jahr'], $m['stunde'], $m['minute']);
}(?<name>…) benennt eine Gruppe; im Treffer-Array steht sie unter diesem Namen (die Nummern gibt es zusätzlich weiter). Verschiebt sich die Reihenfolge, bleibt der Zugriff richtig.
Alle Treffer auf einmal
$log = <<<TXT
2026-09-01 12:03 WARN Speicher knapp
2026-09-01 12:07 ERROR Verbindung verloren
TXT;
preg_match_all('/^(?<datum>[\d-]+) (?<zeit>[\d:]+) (?<stufe>[A-Z]+)\s+(?<text>.+)$/m', $log, $treffer, PREG_SET_ORDER);
foreach ($treffer as $t) {
if ($t['stufe'] === 'ERROR') {
echo $t['datum'], ' ', $t['text'], PHP_EOL;
}
}PREG_SET_ORDER liefert je Fund ein vollständiges Array – deutlich handlicher als die Standardform, bei der man über Spalten iteriert.
Ersetzen mit Logik: preg_replace_callback
Ein Ersetzungsstring kann nur einsetzen, nicht rechnen. Sobald du den gefundenen Wert verändern willst, brauchst du den Rückruf:
// Alle Beträge im Text um 19 % erhöhen und deutsch formatieren
$neu = preg_replace_callback(
'/(?<betrag>\d+(?:[.,]\d{2})?)\s*€/u',
static function (array $m): string {
$wert = (float)str_replace(',', '.', $m['betrag']);
return number_format($wert * 1.19, 2, ',', '.') . ' €';
},
$text
);Das ist auch der saubere Weg, um Platzhalter zu füllen, Links zu bauen oder Umlaute zu normalisieren – alles, was eine Entscheidung je Treffer braucht.
Lesbar bleiben mit dem x-Modifikator
$muster = '/
^(?<nummer>RE-\d{4}) # Rechnungsnummer
\s*\|\s*
(?<kunde>[^|]+) # Kundenname
\s*\|\s*
(?<summe>[\d.,]+)\s*EUR # Betrag
/xu';x ignoriert Leerraum und erlaubt Kommentare im Muster. Genau das macht aus einer Zeile Kryptografie etwas, das man in einem Code-Review verstehen kann.
Fallstrick
Setz bei allem, was Text von Menschen enthält, den u-Modifikator (UTF-8) – ohne ihn zerlegt . einen Umlaut in zwei halbe Bytes. Prüfe außerdem den Rückgabewert: preg_match liefert false bei einem kaputten Muster, und false ist nicht 0; ein if (preg_match(...)) verschluckt diesen Unterschied. Und der wichtigste Rat: Für HTML sind reguläre Ausdrücke das falsche Werkzeug – dafür gibt es DOMDocument.
Textverarbeitung, Importe und Altdaten-Umzüge sind mein täglich Brot. Melde dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Beträge und Zahlen in PHP formatieren – number_format, sprintf und Intl
1234.5 ist keine Anzeige, sondern ein Wert. Auf der Rechnung soll 1.234,50 € stehen, in der API 1234.50 und im Dateinamen 1234-50. Drei Aufgaben, drei Werkzeuge – und ein Fehler, den fast jeder einmal macht.
Benannte Argumente in PHP 8 – Schluss mit true, false, null, true
Ein Aufruf wie erstelle($a, true, false, null, true) sagt nichts darüber, was die Wahrheitswerte bedeuten. Mit benannten Argumenten steht es im Aufruf – und optionale Parameter lassen sich überspringen.
json_decode mit JSON_THROW_ON_ERROR – Fehler, die man nicht übersehen kann
Kaputtes JSON gibt bei json_decode ein stilles null zurück – dasselbe null, das auch im gültigen JSON stehen kann. Ein Flag macht daraus eine Ausnahme, und aus der Fehlersuche wird eine Zeile Stacktrace.