Zum Inhalt springen
aviral gupta

// I5.2 · ca. 35 Min. · Aufbau

Reguläre Ausdrücke: Text finden, prüfen und ersetzen

Nach dieser Lektion prüfen Sie Text gegen ein Muster, holen mit benannten Gruppen die gewünschten Teile heraus und ersetzen oder teilen Text mit einem regulären Ausdruck.

Lektion 2 von 5 in I5 Mit Daten arbeiten

Danach können Sie

  • Ein Muster als Literal oder mit new RegExp schreiben, die Flags g, i, m und u nutzen und Text mit test prüfen
  • Treffer und ihre Gruppen mit match, matchAll und exec holen, auch benannte Gruppen
  • Text mit einem Muster ersetzen und teilen und Benutzertext mit RegExp.escape maskieren
  1. Aufwärmen · Aufgabe 1 von 7

    Zum Aufwärmen aus Lektion I5.1. Ein String ist iterierbar, Buchstabe für Buchstabe. Was gibt das aus?

    console.log([...new Set("banana")].join(""));
  2. Vorhersagen · Aufgabe 2 von 7

    Sagen Sie es vorher, bevor Sie weiterlesen. Was gibt das aus?

    console.log("cat bat".replace("at", "og"));
  3. Üben · Aufgabe 3 von 7

    Ergänzen Sie das Flag, das das Muster Groß- und Kleinschreibung ignorieren lässt.

    console.log(/hello/____.test("Hello World"));
    console.log(/hello/.test("Hello World"));
  4. Üben · Aufgabe 4 von 7

    Ordnen Sie jedem Aufruf zu, was er zurückgibt.

  5. Üben · Aufgabe 5 von 7

    Benannte Gruppen in der Ersetzung. Was gibt das aus?

    const iso = /(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/;
    console.log("2026-10-05".replace(iso, "$<d>.$<m>.$<y>"));
  6. Denksport · Aufgabe 6 von 7

    Knobelaufgabe. Derselbe Test, dreimal, mit dem Flag g. Was gibt das aus?

    const re = /o/g;
    console.log(re.test("foo"), re.test("foo"), re.test("foo"));
  7. Anwenden · Aufgabe 7 von 7

    Kleine Aufgabe: text = "Tea 3.50 EUR, cake 4.20 EUR, coffee 2.80 EUR". Schreiben Sie ein Muster mit den benannten Gruppen item und amount, durchlaufen Sie jeden Treffer mit matchAll, geben Sie für jeden item: amount aus und geben Sie die Summe mit zwei Nachkommastellen aus.

    Prüfen Sie Ihr Ergebnis anhand dieser Liste

Selbst programmieren

Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.

Ausgearbeitetes Beispiel

Daten und Adressen in einem kurzen Text

Ein Text, sieben Fragen. test beantwortet, ob es ein Datum gibt, match mit g listet die Daten auf, und matchAll mit benannten Gruppen nimmt jedes Datum auseinander. replace mit $<day> schreibt die Daten in deutscher Reihenfolge um. Das Flag i findet eine Adresse in Großbuchstaben, und das Flag m lässt ^ am Anfang der zweiten Zeile greifen. Schließlich wird derselbe getippte Text als Muster benutzt, einmal roh und einmal mit RegExp.escape maskiert.

main.js

const text = `Meeting on 2026-10-05 with ada@example.com.
Follow-up on 2026-10-12 with BO@Example.com.`;

// 1. test: is there a date at all?
console.log("has a date:", /\d{4}-\d{2}-\d{2}/.test(text));

// 2. match with the g flag: every date, as strings.
console.log("dates:", text.match(/\d{4}-\d{2}-\d{2}/g).join(" "));

// 3. matchAll with named groups: the parts of each date.
const datePattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/g;
for (const match of text.matchAll(datePattern)) {
  const { day, month, year } = match.groups;
  console.log(`at ${match.index}: day ${day}, month ${month}, year ${year}`);
}

// 4. replace with $<name>: German date order.
const german = text.replace(datePattern, "$<day>.$<month>.$<year>");
console.log(german.split("\n")[0]);

// 5. The i flag: addresses in any case, made lower case.
const emails = text.match(/[a-z]+@example\.com/gi).map((e) => e.toLowerCase());
console.log("emails:", emails.join(", "));

// 6. The m flag: ^ matches at the start of every line.
console.log("lines starting with Follow:", text.match(/^Follow/gm).length);

// 7. RegExp.escape: search for text a user typed.
const typed = "example.com";
const plain = new RegExp(typed);
const escaped = new RegExp(RegExp.escape(typed));
console.log("exampleXcom:", plain.test("exampleXcom"), escaped.test("exampleXcom"));

Ausführen mit

node main.js

Ausgabe

has a date: true
dates: 2026-10-05 2026-10-12
at 11: day 05, month 10, year 2026
at 57: day 12, month 10, year 2026
Meeting on 05.10.2026 with ada@example.com.
emails: ada@example.com, bo@example.com
lines starting with Follow: 1
exampleXcom: true false
  • match.index ist die Stelle, an der der Treffer beginnt, ab 0 gezählt.
  • Ohne das Flag m fände /^Follow/g nichts: ^ würde nur den Anfang des ganzen Texts meinen.
  • Das rohe Muster example.com traf auf exampleXcom, weil . jedes Zeichen bedeutet. Das maskierte traf nicht.
Ändern und ausführen

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.

Übungen

Übung 1 von 2

Eine deutsche Postleitzahl

isPostcode(text) soll nur dann true zurückgeben, wenn der ganze Text eine deutsche Postleitzahl ist: genau fünf Ziffern, etwa "10115". Der Startcode gibt für "123456" und "PLZ 10115" true zurück, weil sein Muster irgendwo im Text passen darf. Verankern Sie das Muster so, dass es den ganzen Text abdecken muss.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Führen Sie die Tests aus: "123456" besteht. Wo im Text darf /\d{5}/ passen?

  2. Hinweis 2

    ^ bedeutet den Anfang des Texts und $ das Ende.

  3. Hinweis 3

    return /^\d{5}$/.test(text);

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

export function isPostcode(text) {
  return /^\d{5}$/.test(text);
}
Auf dem eigenen Computer ausführen

Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.js

export function isPostcode(text) {
  return /\d{5}/.test(text);
}

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {isPostcode} from './main.js';

test('Fünf Ziffern sind eine Postleitzahl', () => {
  assert.equal(isPostcode('10115'), true, 'isPostcode("10115") sollte true sein');
});

test('Vier Ziffern sind zu kurz', () => {
  assert.equal(isPostcode('1011'), false, 'isPostcode("1011") sollte false sein');
});

test('Sechs Ziffern sind zu lang', () => {
  assert.equal(isPostcode('123456'), false, 'isPostcode("123456") sollte false sein');
});

test('Anderer Text um die Ziffern ist keine Postleitzahl', () => {
  assert.equal(isPostcode('PLZ 10115'), false, 'isPostcode("PLZ 10115") sollte false sein');
});

package.json

{
  "type": "module"
}

package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.

Programm ausführen:

node main.js

Prüfungen ausführen (learnrun.js muss im selben Ordner liegen):

node --test
learnrun.js herunterladen

Übung 2 von 2

Eine Uhrzeit mit benannten Gruppen lesen

parseTime(text) soll aus "14:05" oder "9:30" {hours: 14, minutes: 5} mit Zahlen machen und für alles andere null zurückgeben, etwa "noon" oder "14:05pm". Der Startcode stürzt bei Text ohne Treffer ab und gibt die Gruppen als Strings zurück. Verankern Sie das Muster, geben Sie null zurück, wenn exec nichts findet, und wandeln Sie die Gruppen mit Number um.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    exec gibt null zurück, wenn es keinen Treffer gibt, und null.groups wirft. Prüfen Sie zuerst auf null.

  2. Hinweis 2

    Gruppen sind immer Strings: Number(match.groups.hours) liefert eine Zahl.

  3. Hinweis 3

    Setzen Sie ^ vor die Stunden und $ hinter die Minuten, damit "14:05pm" nicht passt.

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

export function parseTime(text) {
  const match = /^(?<hours>\d{1,2}):(?<minutes>\d{2})$/.exec(text);
  if (match === null) return null;
  return { hours: Number(match.groups.hours), minutes: Number(match.groups.minutes) };
}
Auf dem eigenen Computer ausführen

Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.js

export function parseTime(text) {
  const match = /(?<hours>\d{1,2}):(?<minutes>\d{2})/.exec(text);
  return { hours: match.groups.hours, minutes: match.groups.minutes };
}

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {parseTime} from './main.js';

test('14:05 ergibt die Zahlen 14 und 5', () => {
  const got = parseTime('14:05');
  assert.deepEqual(got, {hours: 14, minutes: 5}, `parseTime('14:05') gab ${JSON.stringify(got)}`);
});

test('Einstellige Stunden funktionieren', () => {
  const got = parseTime('9:30');
  assert.deepEqual(got, {hours: 9, minutes: 30}, `parseTime('9:30') gab ${JSON.stringify(got)}`);
});

test('Text ohne Uhrzeit ergibt null', () => {
  assert.equal(parseTime('noon'), null, 'parseTime("noon") sollte null sein');
});

test('Zusätzlicher Text nach der Uhrzeit ergibt null', () => {
  assert.equal(parseTime('14:05pm'), null, 'parseTime("14:05pm") sollte null sein');
});

package.json

{
  "type": "module"
}

package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.

Programm ausführen:

node main.js

Prüfungen ausführen (learnrun.js muss im selben Ordner liegen):

node --test
learnrun.js herunterladen

Häufige Fehler

replaceAll mit einem Regex ohne g

const date = "2026-10-05";
console.log(date.replaceAll(/-/, "/"));

Was Node.js ausgibt

TypeError: String.prototype.replaceAll called with a non-global RegExp argument

Warum, und die Lösung

replaceAll soll jeden Treffer ersetzen, ein Regex ohne das Flag g wird deshalb abgelehnt. Ergänzen Sie das Flag: date.replaceAll(/-/g, "/"). Mit g tut date.replace(/-/g, "/") dasselbe. matchAll hat dieselbe Regel.

Ein einzelner Backslash in einem RegExp-String

const digits = new RegExp("\d+");
const total = "Total: 42 EUR".match(digits)[0];
console.log(Number(total));

Was Node.js ausgibt

TypeError: Cannot read properties of null (reading '0')

Warum, und die Lösung

In einem String ist "\d" nur der Buchstabe d, das Muster ist also d+, das im Text nicht vorkommt, und match gibt null zurück. Verdoppeln Sie den Backslash in einem String, new RegExp("\\d+"), oder nutzen Sie das Literal /\d+/. Und prüfen Sie auf null, bevor Sie [0] oder groups lesen.

Getippten Text als Muster verwenden

const typed = "(1+1";
const search = new RegExp(typed);
console.log(search.test("Is (1+1 = 2) true?"));

Was Node.js ausgibt

SyntaxError: Invalid regular expression: /(1+1/: Unterminated group

Warum, und die Lösung

Der Benutzer meinte die Zeichen ( und +, aber in einem Muster öffnet ( eine Gruppe und + wiederholt. Eine offene Gruppe ohne ) ist kein gültiges Muster, also wirft new RegExp. Maskieren Sie den Text zuerst: new RegExp(RegExp.escape(typed)). Dann steht jedes Zeichen nur für sich selbst.

JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode

Abschlussquiz

5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.

Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.

Problem melden

Etwas ist falsch oder unklar? Beschreiben Sie es kurz, dann wird es geprüft und korrigiert.

#

Mindestens 20 Zeichen.

Nur, wenn Sie eine Antwort wünschen.

Kernideen

Muster und Flags

Ein regulärer Ausdruck ist ein Muster für Text. Schreiben Sie ihn als Literal, /\d{4}/, oder bauen Sie ihn aus einem String mit new RegExp("\\d{4}"). In einem String muss jeder Backslash verdoppelt werden, weil "\d" in einem String nur d ist. Flags stehen hinter dem schließenden Schrägstrich oder als zweites Argument: g findet jeden Treffer, i ignoriert die Schreibweise, m lässt ^ und $ an jeder Zeile greifen, und u liest den Text als Unicode-Codepoints, ein Emoji zählt also als ein Zeichen. ^ und $ verankern das Muster an Anfang und Ende; ohne sie ist test wahr, wenn das Muster irgendwo vorkommt. pattern.test(text) antwortet mit true oder false.

Treffer und Gruppen

text.match(pattern) ohne g liefert den ersten Treffer als Array, mit index und groups, oder null, wenn nichts passt; behandeln Sie null immer. Mit g liefert match ein Array aller gefundenen Strings und keine Gruppen. text.matchAll(pattern) braucht g und liefert jeden Treffer mit seinen Gruppen, ideal für eine for...of-Schleife. Runde Klammern fangen einen Teil ein: match[1] ist die erste Gruppe. Eine benannte Gruppe, (?<year>\d{4}), liest man als match.groups.year, was richtig bleibt, wenn Sie später Gruppen ergänzen. pattern.exec(text) funktioniert wie match ohne g; mit g merkt sich ein Regex lastIndex zwischen den Aufrufen, und test ebenso.

Ersetzen, Teilen und Maskieren

text.replace(pattern, replacement) gibt einen neuen String zurück. Bei einem String-Muster oder einem Regex ohne g wird nur der erste Treffer ersetzt; mit g alle. replaceAll tut dasselbe, wirft aber bei einem Regex ohne g einen TypeError. In der Ersetzung fügen $1 oder $<name> eine Gruppe ein, und eine Funktion bekommt jeden Treffer und gibt seine Ersetzung zurück. text.split(/\s*,\s*/) teilt an Kommas mit beliebigen Leerzeichen drumherum. Vom Benutzer getippter Text kann . ( + oder ? enthalten, die in einem Muster etwas bedeuten. RegExp.escape(text) maskiert sie, sodass new RegExp(RegExp.escape(text)) genau diesen Text findet.

Quellen

Zuletzt geprüft am 5. Oktober 2026