MWCodebymw.de ↗
PHP

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

#PHP#Regex#preg_match#Textverarbeitung#Muster

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 →