Suchen und Ersetzen mit Regex: Backreference
Backreferenzen speichern Teile eines Treffers oder Matches und verwenden sie beim Ersetzen erneut. Backreferenzen sind ideal, um Daten umzustrukturieren und nicht nur zu ersetzen. Runde Klammern im regulären Ausdruck (…) bilden Gruppen und sind der Speicher für Teilstrings: Das ist ein Rückverweis (Backreferenz) des regulären Ausdrucks.
Ersetzen mit Backtracking
Bei der Auswertung eines regulären Ausdrucks liest der Interpreter die Zeichenkette Zeichen für Zeichen ein und vergleicht jedes Zeichen mit der entsprechenden Stelle des regulären Ausdrucks. Dabei merkt sich der Interpreter die Stellen, an denen es mehr als eine Möglichkeit gibt und wenn der Interpreter beim Testen einer Variante feststellt, dass der Gesamtausdruck nicht mehr zutrifft, kehr er an diese Stelle zurück und prüft die Alternative.
Das klassische Beispiel für Suchen und Ersetzen mit Backreferenz ist das Tauschen von "Nachname, Vorname" gegen "Vorname Nachname", etwa wenn "Nachname, Vorname" aus JSON übernommen wird.
const books = [
{ "titel": "Ein Toter zu wenig", "autor": "Sayers, Dorothy", "img": "img/toter-zu-wenig.webp" },
{ "titel": "Stolz und Vorurteil", "autor": "Austen, Jane", "img": "img/stolz-und-vorurteil.webp" },
{ "titel": "Brusel", "autor": "Schuiten et Peeters", "img": "img/xml-brusel.webp" },
{ "titel": "Raumschiff Titanic", "autor": "Adams, Douglas", "img": "img/douglas-adams-raumschiff-titanic.jpg" }
]
const booksWithSwappedAuthors = books.map(book => ({
...book,
autor: book.autor.replace(/^\s*([^,]+),\s*(.+)\s*$/, "$2 $1")
▲ ▲ ▲ ▲
│ │ │ │
Anfang erster Ausdruck ┘ │ │ └ Ende zweiter Ausdruck
Ende erster Ausdruck ┘ └ Anfang zweiter Ausdruck
}));
console.log(booksWithSwappedAuthors);
Dieses „Backtracking“ erlaubt numerierte Rückbezüge auf geklammerte Ausdrücke. Alle Ausdrücke in runden Klammern bilden Gruppen, die von links nach rechts durchnummeriert werden.
Named Capturing Groups
Named Capturing Groups sind mit ES2018 (ES9) eingezogen und verbessern die Lesbarkeit der Fragmente. (?<name>...) → benennt die Capture Group.
const regex = /^(?<nachname>[^,]+),\s*(?<vorname>.+)$/;
Das ist besser wartbar, selbsterklärend und weniger fehleranfällig und wird zuverlässig von allen modernen Browsern unterstützt
const match = autor.match( /^(?<nachname>[^,]+),\s*(?<vorname>.+)$/ ); console.log(match.groups.vorname); // Dorothy console.log(match.groups.nachname); // Sayers
Regex-Gruppen
Beide reguläre Ausdrücke finden dieselbe Folge von Ziffern in einem Text, aber der zweite Ausdruck kann später durch eine besondere Variable für ein Backreference (Rückverweis) aus dem Gedächtnis geholt und mit $Num angesprochen werden:
/\d+/ /(\d+)/
In einem regulären Ausdruck lassen sich Teile des Musters in runde Klammern (…) setzen. Gruppen in runden Klammern (sogen. Capture-Gruppen) werden z.B. für ein "oder" eingesetzt: Suche ä oder ae: /(ä|ae)/.
Außerhalb des regulären Ausdrucks – z.B. im Ersetzungsteil – wird die besondere Variable durch $1 für die erste runde Klammer, $2 für die zweite, … bis $99 verwendet.
Diese Namenskonvention für Variablen – $ – hat Javascript aus Perl genommen (PHP-Programmierer kennen diese Schreibweise für Variablennamen ebenfalls). Hat also an dieser Stelle nichts mit jQuery zu tun …
Capture-Gruppen mit Namen
Alles, was mit den Ausdrücken in diesen runden Klammern matcht – passt – wird eingefangen (captured) und für später zugreifbar gemacht.
const str = "2025-09-21";
erste Gruppe ┐ ┌ zweite Gruppe
│ │ ┌ dritte Gruppe
▼ ▼ ▼
const re = /(\d{4})-(\d{2})-(\d{2})/;
const result = str.match(re);
console.log(result);
- "2025", // [1] = erste Capture-Gruppe (\d{4})
- "09", // [2] = zweite Gruppe (\d{2})
- "21" // [3] = dritte Gruppe (\d{2})
Und auch hier gilt wieder: Das sieht mit Named Capturing Groups viel besser aus.
const res = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const result = "2025-09-21".match(res);
console.log(result.groups.year); // "2025"
console.log(result.groups.month); // "09"
console.log(result.groups.day); // "21"
Und ganz einfach das Format umstellen:
const out = "2025-02-20".replace( re, "$<day>.$<month>.$<year>" ); console.log(out); // 20.02.2025
URL zu Link
Alle URLs in klickbare Links umwandeln
Reguläre Ausdrücke bei https://www.mediaevent.de/html/input-pattern.html und auf https://www.mediaevent.de/javascript/string-search.html
<p class="text">Reguläre Ausdrücke bei https://www.mediaevent.de/html/input-pattern.html und auf https://www.mediaevent.de/javascript/string-search.html</p>
let text = document.querySelector(".text").innerHTML;
text = text.replace(/(https?:\/\/[^ ]+)/g, (match, link) => {
// einen evt. Slash am Ende ersetzen
link = link.replace(/\/?$/, '');
return `<a href="${link}" target="_blank">${link.substr(link.lastIndexOf('/') +1)}</a>`;
});
document.querySelector(".result").innerHTML = text;
Backreference mit ()
Die Notation $Num ist so intuitiv wie ein Lochstrickmuster.
ISO-Datum als normales Datum anzeigen
Zuweisung mit rexeg.exec (str) ist besser lesbar (um einen Hauch, aber immerhin).<(p>)>
ISO-Datum in normaler Schreibweise
function parseIsoDate(str) {
let matchObj = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(str);
if (!matchObj) {
throw new Error('Kein valides ISO-Datum: ' + str );
}
return matchObj[3] + "." + matchObj[2] + "." + matchObj[1];
}
Named capturing groups sollen in Zukunft die Lesbarkeit der Fragmente verbessern. Gibt es aktuell als babelio.js-Plugin von DmitrySoshnikov.
Alle Treffer einer Suche markieren
string match und string replace funktionieren mit regulären Ausdrücken, aber string text nur mit einer Zeichenkette.
Die Zeichenkette string soll immer in ein mark-Tag eingeschlossen werden. Typische Anwendung: Wenn der Suchbegriff in der Liste der Treffer markiert werden soll.
let str = document.querySelector("#replace").innerHTML.replace(/(string)/ig,"<mark> $1 </mark>");
document.querySelector("#result").innerHTML = str;
Gefunden auf Stackoverflow
Würde auch mit $& anstelle von $1 funktionieren, da hier nur auf eine Gruppe verwiesen wird.