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

Javascript 为什么带有全局标志的RegExp会给出错误的结果?,javascript,regex,Javascript,Regex,当我使用全局标志和不区分大小写标志时,这个正则表达式有什么问题?查询是用户生成的输入。结果应该是[真的,真的] 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; 对于(i=

当我使用全局标志和不区分大小写标志时,这个正则表达式有什么问题?查询是用户生成的输入。结果应该是[真的,真的]

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;
对于(i=0;i++<10;)

控制台日志(注册测试(“a”)
您正在使用单个
RegExp
对象并多次执行它。在每次连续执行时,它将从最后一个匹配索引继续执行

在每次执行之前,您需要“重置”正则表达式以从头开始:

result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
// result is now [true, true]
尽管如此,每次创建一个新的RegExp对象可能更具可读性(由于RegExp是缓存的,所以开销最小):


RegExp.prototype.test
更新正则表达式的
lastIndex
属性,以便每个测试都从最后一个测试停止的位置开始。我建议使用
String.prototype.match
,因为它不会更新
lastIndex
属性:

!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true
result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
注意:
将其转换为布尔值,然后反转布尔值以反映结果

或者,您可以只重置
lastIndex
属性:

!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true
result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));

带有
g
标志的
RegExp
对象跟踪匹配发生的位置,因此在后续匹配中,它将从上次使用的索引开始,而不是从0开始。看一看:

var查询='foob';
var re=new RegExp(查询'gi');
var结果=[];
结果.推(重新测试('Foo-Bar'));
警报(关于最新索引);

结果.推(重新测试('Foo-Bar'))
删除全局
g
标志将解决您的问题

var re = new RegExp(query, 'gi');
应该是


使用/g标志告诉它在命中后继续搜索

在首次搜索之前:

myRegex.lastIndex
//is 0
在第一次搜索之后

myRegex.lastIndex
//is 8
删除g,它在每次调用exec()后退出搜索。

我有一个函数:

function parseDevName(name) {
  var re = /^([^-]+)-([^-]+)-([^-]+)$/g;
  var match = re.exec(name);
  return match.slice(1,4);
}

var rv = parseDevName("BR-H-01");
rv = parseDevName("BR-H-01");
第一个电话有效。 第二个电话没有。
切片
操作抱怨空值。我想这是因为
re.lastIndex
。这很奇怪,因为我希望每次调用函数时都分配一个新的
RegExp
,而不是在多次调用函数时共享

当我把它改成:

var re = new RegExp('^([^-]+)-([^-]+)-([^-]+)$', 'g');

那么我就不会得到
lastIndex
延迟效应。它的工作原理与我所期望的一样。

您需要将re.lastIndex设置为0,因为使用g标志regex跟踪上次发生的匹配,所以test不会去测试同一个字符串,因此您需要执行re.lastIndex=0

var查询='foob';
var re=new RegExp(查询'gi');
var结果=[];
结果.推(重新测试('Foo-Bar'));
re.lastIndex=0;
结果.推(重新测试('Foo-Bar'));

log(result)
欢迎使用JavaScript中RegExp的众多陷阱之一。它有我见过的最糟糕的正则表达式处理接口之一,充满了奇怪的副作用和模糊的警告。您通常希望使用regex执行的大多数常见任务都很难正确拼写。XRegExp看起来是一个不错的选择。请参见此处的答案:如果您可以解决此问题,一个解决方案是直接使用regex文本,而不是将其保存到
re
。这类似于《银河API设计指南》。“如果你只是费心去检查一下”Firefox的粘性标志根本不符合你的意思,那么你陷入的陷阱已经在规范中完美地记录了好几年了。相反,它的行为就像正则表达式的开头有一个“^”,只是该“^”与当前字符串位置(lastIndex)匹配,而不是与字符串的开头匹配。您正在有效地测试正则表达式是否匹配“Righthere”而不是“anywhere after lastIndex”。请参阅您提供的链接!这个答案的开场白并不准确。您突出显示了规范的第3步,但没有说明任何内容。
lastIndex
的实际影响在步骤5、6和11中。只有在设置了全局标志时,您的开场白才是真的。@Prestaul是的,您是对的,它没有提到全局标志。这可能是(不记得我当时是怎么想的)含蓄的,因为这个问题的结构。请随意编辑或删除答案并链接到您的答案。还有,让我向你保证你比我好。享受吧@IonuțG.Stan,如果我之前的评论显得攻击性的话,很抱歉,那不是我的意图。我现在无法编辑它,但我不是想大声喊叫,只是想让大家注意我评论的要点。我的错!OP没有使用
exec
。或者干脆不使用
g
标志。