グローバルフラグ付きの正規表現が間違った結果を返すのはなぜですか? 質問する

グローバルフラグ付きの正規表現が間違った結果を返すのはなぜですか? 質問する

グローバル フラグと大文字と小文字を区別しないフラグを使用する場合、この正規表現の問題は何ですか? クエリはユーザーが生成した入力です。結果は [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"));

ベストアンサー1

RegExpフラグを持つオブジェクトはglastIndex一致が発生した場所なので、後続の一致では 0 ではなく最後に使用されたインデックスから始まります。見てみましょう:

var query = 'Foo B';
var re = new RegExp(query, 'gi');
console.log(re.lastIndex);

console.log(re.test('Foo Bar'));
console.log(re.lastIndex);

console.log(re.test('Foo Bar'));
console.log(re.lastIndex);

lastIndexテストのたびに手動で 0 にリセットしたくない場合は、gフラグを削除するだけです。

仕様で規定されているアルゴリズムは次のとおりです (セクション 15.10.6.2)。

RegExp.prototype.exec(文字列)

文字列と正規表現の一致を実行し、一致の結果を含む配列オブジェクトを返します。文字列が一致しなかった場合は null を返します。文字列 ToString(string) は、次のように正規表現パターンの出現を検索します。

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

おすすめ記事