Gruppen und Rückverweise

Gruppen fassen mehrere Muster als Ganzes zusammen, und erfassende Gruppen liefern zusätzliche Informationen zu Untermatches, wenn ein regulärer Ausdruck verwendet wird, um eine Zeichenkette abzugleichen. Rückverweise beziehen sich auf eine zuvor erfasste Gruppe im gleichen regulären Ausdruck.

Probieren Sie es aus

// Groups
const imageDescription = "This image has a resolution of 1440×900 pixels.";
const regexpSize = /(\d+)×(\d+)/;
const match = imageDescription.match(regexpSize);
console.log(`Width: ${match[1]} / Height: ${match[2]}.`);
// Expected output: "Width: 1440 / Height: 900."

// Backreferences
const findDuplicates = "foo foo bar";
const regex = /\b(\w+)\s+\1\b/g;
console.log(findDuplicates.match(regex));
// Expected output: Array ["foo foo"]

Typen

Zeichen Bedeutung
(x)

Erfassende Gruppe: Passt zu x und merkt sich das Match. Zum Beispiel passt /(foo)/ zu "foo" in "foo bar" und merkt sich dies.

Ein regulärer Ausdruck kann mehrere erfassende Gruppen haben. In den Ergebnissen befinden sich die Matches der erfassenden Gruppen typischerweise in einem Array, dessen Elemente in der gleichen Reihenfolge wie die linken Klammern der erfassenden Gruppe sind. Dies ist normalerweise die Reihenfolge der erfassenden Gruppen selbst. Dies wird wichtig, wenn erfassende Gruppen verschachtelt sind. Matches werden mit dem Index der Elemente des Ergebnisses ([1], …, [n]) oder von den vordefinierten Eigenschaften des RegExp-Objekts ($1, …, $9) abgerufen.

Erfassende Gruppen haben einen Performance-Nachteil. Wenn Sie den erfassten Unterstring nicht erneut verwenden müssen, bevorzugen Sie nicht-erfassende Klammern (siehe unten).

String.prototype.match() gibt keine Gruppen zurück, wenn das /.../g Flag gesetzt ist. Sie können jedoch weiterhin String.prototype.matchAll() verwenden, um alle Matches zu erhalten.

(?<Name>x)

Benannte erfassende Gruppe: Passt zu "x" und speichert es in der Eigenschaft `groups` der zurückgegebenen Matches unter dem angegebenen Namen <Name>. Die spitzen Klammern (< und >) sind für den Gruppennamen erforderlich.

Zum Beispiel, um die amerikanische Vorwahl aus einer Telefonnummer zu extrahieren, könnten wir /\((?<area>\d\d\d)\)/ verwenden. Die resultierende Nummer würde unter matches.groups.area erscheinen.

(?:x)

Nicht-erfassende Gruppe: Passt zu "x", merkt sich das Match aber nicht. Der abgeglichene Unterstring kann nicht aus den Elementen des resultierenden Arrays ([1], …, [n]) oder von den vordefinierten Eigenschaften des RegExp-Objekts ($1, …, $9) abgerufen werden.

(?flags:x), (?:flags-flags:x)

Modifikator: Aktiviert oder deaktiviert die angegebenen Flags nur für das eingeschlossene Muster. Nur die Flags i, m und s können in einem Modifikator verwendet werden.

\n

Rückverweis: Wo "n" eine positive ganze Zahl ist. Passt zu dem gleichen Unterstring, der von der n-ten erfassenden Gruppe im regulären Ausdruck (linke Klammer zählend) abgeglichen wurde. Zum Beispiel, /apple(,)\sorange\1/ passt zu "apple, orange," in "apple, orange, cherry, peach".

\k<Name>

Benannter Rückverweis: Ein Rückverweis auf das letzte Teilstring-Match der benannten erfassenden Gruppe, die durch <Name> angegeben ist.

Zum Beispiel, /(?<title>\w+), yes \k<title>/ passt zu "Sir, yes Sir" in "Do you copy? Sir, yes Sir!".

Hinweis: \k wird hier wörtlich verwendet, um den Beginn eines Rückverweises auf eine benannte erfassende Gruppe anzuzeigen.

Beispiele

Verwendung von Gruppen

In diesem Beispiel gleichen wir zwei Wörter in einem strukturierten Format ab, indem wir erfassende Gruppen verwenden, um sie sich zu merken. \w+ passt zu einem oder mehreren Wortzeichen, und die Klammern () erstellen eine erfassende Gruppe. Das g-Flag wird verwendet, um alle Vorkommen abzugleichen.

js
const personList = `First_Name: John, Last_Name: Doe
First_Name: Jane, Last_Name: Smith`;

const regexpNames = /First_Name: (\w+), Last_Name: (\w+)/g;
for (const match of personList.matchAll(regexpNames)) {
  console.log(`Hello ${match[1]} ${match[2]}`);
}

Weitere Beispiele finden Sie im Referenzdokument zur erfassenden Gruppe.

Verwendung benannter Gruppen

Dieses Beispiel ist dasselbe wie oben, jedoch verwenden wir benannte erfassende Gruppen, um die abgeglichenen Wörter stattdessen zu merken. Auf diese Weise können wir auf die abgeglichenen Wörter nach ihren Bedeutungen zugreifen.

js
const personList = `First_Name: John, Last_Name: Doe
First_Name: Jane, Last_Name: Smith`;

const regexpNames =
  /First_Name: (?<firstName>\w+), Last_Name: (?<lastName>\w+)/g;
for (const match of personList.matchAll(regexpNames)) {
  console.log(`Hello ${match.groups.firstName} ${match.groups.lastName}`);
}

Weitere Beispiele finden Sie im Referenzdokument zur benannten erfassenden Gruppe.

Verwendung von Gruppen und Rückverweisen

In diesem Beispiel gleichen wir zuerst ein einzelnes oder doppeltes Anführungszeichen mit ['"] ab, merken es uns, gleichen eine beliebige Anzahl von Zeichen mit .*? ab (*? ist ein nicht-gieriger Quantifizierer), bis wir das gemerkte Anführungszeichenzeichen wieder mit \1 abgleichen. Die \1 ist ein Rückverweis auf die erste erfassende Gruppe, die denselben Anführungszeichentyp abgleicht. Das Ergebnis sind daher zwei Zeichenfolgen: "'" und '"'.

js
const quote = `Single quote "'" and double quote '"'`;
const regexpQuotes = /(['"]).*?\1/g;
for (const match of quote.matchAll(regexpQuotes)) {
  console.log(match[0]);
}

Weitere Beispiele finden Sie im Referenzdokument zum Rückverweis.

Verwendung von Gruppen und Match-Indizes

Mit dem d-Flag werden die Indizes jeder erfassenden Gruppe zurückgegeben. Dies ist besonders nützlich, wenn Sie jede abgeglichene Gruppe mit dem ursprünglichen Text korrelieren möchten — zum Beispiel um Compiler-Diagnosen bereitzustellen.

js
const code = `function add(x, y) {
  return x + y;
}`;
const functionRegexp =
  /(function\s+)(?<name>[$_\p{ID_Start}][$\p{ID_Continue}]*)/du;
const match = functionRegexp.exec(code);
const lines = code.split("\n");
lines.splice(
  1,
  0,
  " ".repeat(match.indices[1][1] - match.indices[1][0]) +
    "^".repeat(match.indices.groups.name[1] - match.indices.groups.name[0]),
);
console.log(lines.join("\n"));
// function add(x, y) {
//          ^^^
//   return x + y;
// }

Siehe auch