一尘不染

为什么带有全局标志的RegExp给出错误的结果?

javascript

当我使用全局标志和不区分大小写的标志时,此正则表达式有什么问题?查询是用户生成的输入。结果应该是[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"));

阅读 313

收藏
2020-04-22

共1个答案

一尘不染

RegExp对象跟踪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(字符串)

对正则表达式执行字符串的正则表达式匹配,并返回包含匹配结果的Array对象;如果字符串不匹配,则返回null。在字符串ToString(string)中搜索正则表达式模式的出现,如下所示:

  1. 令S为ToString(string)的值。
  2. 令length为S的长度。
  3. 令lastIndex为lastIndex属性的值。
  4. 令我为ToInteger(lastIndex)的值。
  5. 如果全局属性为false,则让i = 0。
  6. 如果I <0或I> length,则将lastIndex设置为0并返回null。
    7.
    调用[[Match]],为其指定参数S和i。如果[[Match]]返回失败,请转到步骤8;否则,请转到步骤8。否则,使r为其State结果,然后转到步骤10。
  7. 令i = i + 1。
  8. 转到步骤6。
  9. 令e为r的endIndex值。
  10. 如果global属性为true,则将lastIndex设置为e。
  11. 令n为r的捕获数组的长度。(此值与15.10.2.1的NCapturingParens相同。)
  12. 返回具有以下属性的新数组:
    • index属性设置为匹配的字符串在完整字符串S中的位置。
    • 输入属性设置为S。
    • length属性设置为n + 1。
    • 将0属性设置为匹配的子字符串(即,偏移量i包括端和偏移量e排除之间的S部分)。
    • 对于使i> 0并且I≤n的每个整数i,将名为ToString(i)的属性设置为r的捕获数组的第i个元素。
2020-04-22