1. ホーム
  2. ジャバスクリプト

[解決済み】グローバルフラグを持つRegExpが間違った結果を出すのはなぜですか?

2022-03-27 06:46:02

質問

この正規表現で、globalフラグとcase insensitiveフラグを使用した場合の問題点は何ですか?クエリーはユーザーが作成した入力です。結果は[true, true]であるべきです。

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
result.push(re.test('Foo Bar'));
// result will be [true, false]


var reg = /^a$/g;
for(i = 0; i++ < 10;)
   console.log(reg.test("a"));

解決方法は?

A RegExp オブジェクトに g フラグは lastIndex そのため、それ以降のマッチでは 0 ではなく最後に使われたインデックスから開始されます。

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));

alert(re.lastIndex);

result.push(re.test('Foo Bar'));

を手動でリセットしたくない場合は lastIndex を 0 にすることで、テストごとに g フラグを使用します。

以下は、仕様で決められているアルゴリズムです(15.10.6.2項)。

RegExp.prototype.exec(string)

を実行します。 文字列の正規表現マッチ を正規表現と比較し を含むArrayオブジェクトを返します。 の場合、NULLとなります。 文字列にマッチしなかった場合 ToString(string)が検索されます。 の出現は、正規表現 パターンを以下のように設定します。

  1. レッツ R はこのRexExpオブジェクトです。
  2. S はToString(string)の値である。
  3. 長さ の長さである。 S .
  4. のlastIndexプロパティの値をlastIndexとする。 R .
  5. ToInteger(lastIndex)の値をiとする。
  6. グローバルプロパティが false の場合、i = 0 とする。
  7. i < 0またはi >lengthの場合、以下のように設定します。 lastIndex のプロパティは R を 0 に設定して null を返します。
  8. 引数Sとiを与えて[[Match]]を呼び出します。 は失敗を返したので、手順9に進む。 そうでなければ、r をその State 結果とする で、ステップ10に進む。
  9. i = i+1 とする。
  10. ステップ7に進みます。
  11. rのendIndexの値をeとする。
  12. グローバルプロパティがtrueの場合 lastIndex のプロパティは R をeに変換する。
  13. rのキャプチャ配列の長さをnとする。(これは という値は、15.10.2.1 の NCapturingParens.)
  14. 以下のプロパティを持つ新しい配列を返す。
  • インデックス プロパティに設定されます。 マッチした部分文字列を完全な 文字列S.
  • 入力プロパティが設定される をSに変換します。
  • 長さプロパティは n + 1.
  • 0 プロパティに設定されます。 マッチした部分文字列(すなわち Sのオフセットiを含むと オフセットeを除く)。
  • 各 i > 0 かつ i ≤ n であるような整数 i。 ToString(i)という名前のプロパティを rのキャプチャ配列の第i番目の要素。