グループと後方参照

グループは複数のパターンを全体としてグループ化し、グループをキャプチャすることで、正規表現パターンを使用して文字列と一致する場合に、追加の副一致情報を提供します。後方参照は、同じ正規表現で以前に捕捉したグループを参照します。

試してみましょう

種類

文字 意味
(x)

キャプチャグループ: x に一致し、一致した内容を記憶します。例えば /(foo)/ は "foo bar" の "foo" に一致し、記憶します。

正規表現は複数のキャプチャグループを持つことができます。結果、一般的にキャプチャグループ内の左括弧と同じ順にある、配列の要素のキャプチャグループに一致しています。たいていの場合、これはキャプチャグループ自身の順番です。これはキャプチャグループがネストしている場合に重要です。一致は結果の要素の添字 ([1], …, [n]) や、あらかじめ定義されている RegExp オブジェクトのプロパティ ($1, …, $9) を使ってアクセスできます。

キャプチャグループはパフォーマンス上の損失があります。一致した部分文字列を使わない場合はキャプチャしない括弧(後述)を使ったほうがいいでしょう。

String.prototype.match() は、/.../g フラグが設定されている場合、グループを返しません。しかし、 String.prototype.matchAll() を使用して、すべての一致したものを取得することができます。

(?<Name>x)

名前付きキャプチャグループ: "x" に一致し、<Name> で指定された名前に従い、返される一致の groups プロパティに記憶されます。山括弧 ('<' と '>') にはグループ名が必須です。

例えば、電話番号からアメリカのエリアコードを取り出す際、 /\((?<area>\d\d\d)\)/ を使うことができます。 結果の番号は matches.groups.area に表示されます。

(?:x) 非キャプチャグループ: "x" に一致しますが、一致した内容は記憶しません。一致した部分文字列は、結果の配列の要素 ([1], …, [n]) や、あらかじめ定義されている RegExp オブジェクトのプロパティ ($1, …, $9) から呼び出すことはできません。

\n

"n" に正の整数が入ります。正規表現内において n 番目の括弧の部分に一致した最新の部分文字列への後方参照となります(括弧の数は左からカウントします)。例えば /apple(,)\sorange\1/ は "apple, orange, cherry, peach" の "apple, orange," に一致します。

\k<Name>

<Name> で指定された名前付きキャプチャグループに一致する最後の部分文字列の後方参照です。

例えば、 /(?<title>\w+), yes \k<title>/ は、 "Do you copy? Sir, yes Sir!" の中の "Sir, yes Sir" に一致します。

メモ: \k は、ここでは、名前付きキャプチャグループの後方参照を開始することを示すために使用されています。

グループの使用

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

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

名前付きグループの使用

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+)/gm;
for (const match of personList.matchAll(regexpNames)) {
  console.log(`Hello ${match.groups.firstname} ${match.groups.lastname}`);
}

グループと後方参照の使用

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

グループと一致結果の添字の使用

d フラグが指定された場合、各キャプチャグループの添字を返します。これは、それぞれの一致したグループと元のテキストを関連付ける場合、例えば、コンパイラーの診断を提供する場合に特に有益です。

js
const code = `function add(x, y) {
  return x + y;
}`;
const functionRegexp =
  /(function\s+)(?<name>[$_\p{ID_Start}][$\u200c\u200d\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;
// }

関連情報