String.prototype.matchAll

公開 · タグとして ECMAScript ES2020 を使用

同じ正規表現を同じ文字列に繰り返し適用して一致をすべて取得することは一般的です。ある程度は、String#match メソッドを使用して現在すでにそれが可能です。

この例では、16 進数の数字のみで構成される単語をすべて見つけて、それぞれの照合をログに出力します

const string = 'Magic hex numbers: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.match(regex)) {
console.log(match);
}

// Output:
//
// 'DEADBEEF'
// 'CAFE'

しかし、このコードでは一致する部分文字列のみが得られます。通常、部分文字列だけでなく、各部分文字列のインデックスや各一致内のキャプチャ グループなどの追加情報も必要です。

独自のループを作成し、各一致オブジェクトを独自に追跡することですでに実現できますが、少し煩わしく、あまり便利ではありません

const string = 'Magic hex numbers: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
let match;
while (match = regex.exec(string)) {
console.log(match);
}

// Output:
//
// [ 'DEADBEEF', index: 19, input: 'Magic hex numbers: DEADBEEF CAFE' ]
// [ 'CAFE', index: 28, input: 'Magic hex numbers: DEADBEEF CAFE' ]

新しい String#matchAll API を使用すると、今まで以上に簡単に取得できます。for-of ループを記述するだけで、すべての一致オブジェクトを取得できます。

const string = 'Magic hex numbers: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.matchAll(regex)) {
console.log(match);
}

// Output:
//
// [ 'DEADBEEF', index: 19, input: 'Magic hex numbers: DEADBEEF CAFE' ]
// [ 'CAFE', index: 28, input: 'Magic hex numbers: DEADBEEF CAFE' ]

String#matchAll はキャプチャ グループを使用した正規表現に特に役立ちます。キャプチャ グループを含む、それぞれの個々の一致の完全な情報を取得できます。

const string = 'Favorite GitHub repos: tc39/ecma262 v8/v8.dev';
const regex = /\b(?<owner>[a-z0-9]+)\/(?<repo>[a-z0-9\.]+)\b/g;
for (const match of string.matchAll(regex)) {
console.log(`${match[0]} at ${match.index} with '${match.input}'`);
console.log(`→ owner: ${match.groups.owner}`);
console.log(`→ repo: ${match.groups.repo}`);
}

// Output:
//
// tc39/ecma262 at 23 with 'Favorite GitHub repos: tc39/ecma262 v8/v8.dev'
// → owner: tc39
// → repo: ecma262
// v8/v8.dev at 36 with 'Favorite GitHub repos: tc39/ecma262 v8/v8.dev'
// → owner: v8
// → repo: v8.dev

一般的な考え方は、簡単な for-of ループを記述し、String#matchAll で残りを処理させるというものです。

注意: その名前が示すように、String#matchAllすべての一致オブジェクトを反復処理することを意図しています。したがって、グローバル正規表現、つまり g フラグが設定されたものと一緒に使用する必要があります。それ以外のグローバルではない正規表現は単一の一致(最大)のみを生成するからです。グローバルではない正規表現で matchAll を呼び出すと、TypeError 例外が発生します。

String.prototype.matchAll のサポート #