问题描述
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 节):
对正则表达式执行字符串的正则表达式匹配,并返回一个包含匹配结果的 Array 对象,如果字符串不匹配,则返回 null 搜索字符串 ToString(string) 以查找正则表达式模式的出现,如下所示:
- 让 R 成为这个 RexExp 对象。
- 令 S 为 ToString(string) 的值。
- 令 length 为 S 的长度。
- 设 i 为 ToInteger(lastIndex) 的值。
- 如果全局属性为假,则令 i = 0。
- 如果 i < 0 或 i > 长度,则将 R的 lastIndex 属性设置为 0 并返回 null。 __
- 调用 [[Match]],给它参数 S 和 i。如果 [[Match]] 返回失败,则转到步骤 9;否则令 r 为其状态结果并转到步骤 10。
- 令 i = i+1。
- 转到步骤 7。
- 设 e 为 r 的 endindex 值。
- 令 n 为 r 的捕获数组的长度。(这与 15.10.2.1 的 NCCapturingParens 的值相同。)
返回具有以下属性的新数组:
index 属性设置为完整字符串 S 中匹配子字符串的位置。
- 输入属性设置为 S。
- 长度属性设置为 n + 1。
- 0 属性设置为匹配的子字符串(即 S 的偏移量 i 包含和偏移量 e 不包含之间的部分)。
- 对于每个整数 i,使得 i > 0 并且 i≥ n,将名为 ToString(i) 的属性设置为 r 的捕获数组的第 i 个元素。
解决方法
当我使用全局标志和不区分大小写标志时,这个正则表达式有什么问题?查询是用户生成的输入。结果应该是 [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"));