String.prototype.matchAll() で結果の一致率を向上

Joe Medley
Joe Medley

Chrome 73 で String.prototype.matchAll() メソッドが導入されました。この動作は match() と似ていますが、グローバル正規表現またはスティッキー正規表現のすべての正規表現一致を含むイテレータを返します。これにより、特にグループをキャプチャするためにアクセス権が必要な場合に、簡単に一致を反復処理できます。

match() の問題点

簡潔に言うと、キャプチャ グループとのグローバルな一致を返そうとしない限り、何もありません。プログラミング パズルをどうぞ。次のコードについて考えてみましょう。

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const results = string.match(regex);
console.log(results);
// → ['test1', 'test2']

これをコンソールで実行すると、文字列 'test1''test2' を含む配列が返されます。正規表現から g フラグを削除すると、キャプチャ グループはすべて取得されますが、最初の一致しか得られません。たとえば、次のようになります。

['test1', 'e', 'st1', '2', index: 0, input: 'test1test2', groups: undefined]

この文字列には、'test2' で始まる 2 つ目の一致が含まれていますが、存在しません。ではパズルに、各マッチのキャプチャ グループをすべて取得するにはどうすればよいでしょうか。String.prototype.matchAll() の提案の説明では、2 つのアプローチが示されています。今後は必要なくなることを願うため ここでは説明しません

String.prototype.matchAll()

matchAll() を使用した場合、説明の例はどのように表示されますか?ぜひ夜空を見上げてみてください。

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const matches = string.matchAll(regex);
for (const match of matches) {
  console.log(match);
}

いくつか注意すべき点があります。グローバル検索で配列を返す match() とは異なり、matchAll()for...of ループで適切に動作するイテレータを返します。イテレータは、一致ごとに配列を生成します。これには、キャプチャ グループといくつかのエクストラが含まれます。これらをコンソールに出力すると、次のようになります。

['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', groups: undefined]
['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]

各一致の値は、非グローバル正規表現に対して match() が返す形式とまったく同じ形式の配列です。

ボーナス資料

主に、正規表現を初めて使用する方や、精通していない方を対象としています。match() と matchAll() の両方の結果が(反復処理ごとに)配列であり、名前付きプロパティが追加されています。この記事を準備している間に、これらのプロパティには MDN に関するドキュメントに不備があることがわかりました(修正済みです)。簡単にご説明しましょう。

index
元の文字列の最初の結果のインデックス。上記の例では、test2 の位置は 5 であるため、index の値は 5 になります。
input
matchAll() が実行された完全な文字列。私の例では 'test1test2' でした。
groups
正規表現で指定された名前付きキャプチャ グループの結果が含まれます。

おわりに

他にご不明な点などございましたら、下のコメント欄からお知らせください。JavaScript に関する最近の変更について詳しくは、以前のアップデートまたは V8 のウェブサイトをご覧ください。