JavaScript

String.prototype.matchAll()メソッド

 編集:2022.08.16 by T.A.

その String に対して正規表現 regexp で全てに一致する部分をイテレーターで返します。

構文
イテレーター= String.matchAll(regexp)
String
regexp 正規表現オブジェクトです。

RegExp でないオブジェクト obj が渡された場合は RegExp オブジェクトに new RegExp(obj) を使用して暗黙的に変換されます。

RegExp オブジェクトには /g フラグが必須であり、ない場合は TypeError が発生します。

戻り値

(再起動不可能なもの)。

Regexp.exec() と matchAll()

matchAll が JavaScript に追加される前は、regexp.exec(および /g フラグ付きの正規表現)をループの中で呼び出すことですべての一致結果を取得することができました。

const regexp = RegExp('foo[a-z]*','g');
const str = 'table football, foosball';
let match;

while ((match = regexp.exec(str)) !== null) {
  alert(`Found ${match[0]} start=${match.index} end=${regexp.lastIndex}.`);
  // 期待される出力:"Found football start=6 end=14."
  // 期待される出力:"Found foosball start=16 end=24."
}

matchAll が使えるようになったことで、while によるループと、g 付きの exec を避けることができます。

また代わりに matchAll を使うことで、for...of、配列スプレッド、Array.from() 構造と効率よく組み合わせることができます。

const regexp = RegExp('foo[a-z]*','g');
const str = 'table football, foosball';
const matches = str.matchAll(regexp);

for (const match of matches) {
  alert(`Found ${match[0]} start=${match.index} end=${match.index + match[0].length}.`);
}
// 期待される出力:"Found football start=6 end=14."
// 期待される出力:"Found foosball start=16 end=24."

// for..of 反復の後で、matches イテレーターが使い果たされる 新しいイテレーターを作成するために、もう一度 matchAll を呼び出します。
D=Array.from(str.matchAll(regexp), m => m[0]); //=[ "football", "foosball" ]

matchAll は、グローバル「g」フラグがない場合は例外が発生します。

const regexp = RegExp('[a-c]','');
const str = 'abc';
str.matchAll(regexp);
// TypeError

matchAll では内部的に RegExp オブジェクトをクローンします。そのため regexp.exec() とは違って文字列をスキャンした際に lastIndex が変わることはありません。

const regexp = RegExp('[a-c]','g');
regexp.lastIndex = 1;
const str = 'abc';
D=Array.from(str.matchAll(regexp), m => `${regexp.lastIndex} ${m[0]}`); //=[ "1 b", "1 c" ]
キャプチャリンググループへのより良いアクセス(String.prototype.match()との比較)

matchAll はキャプチャー グループへのよりよいアクセスを実現します。

match() では、グローバル「/g」フラグを使用するとキャプチャー グループが無視されてしまいます。

let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';
D=str.match(regexp); //=['test1', 'test2']

// matchAll を使えば簡単にキャプチャー グループにアクセスできます。
let array = [...str.matchAll(regexp)];
D=array[0]; //={0:'test1', 1:'e', 2:'st1', 3:'1', index:0, input:'test1test2', length:4}
D=array[1]; //={0:'test2', 1:'e', 2:'st2', 3:'2', index:5, input:'test1test2', length:4}

テスト