为什么Javascript正则表达式每秒都匹配一次?

为什么Javascript正则表达式每秒都匹配一次?,javascript,regex,Javascript,Regex,我定义一个regex对象,然后在循环中匹配它。准确地说,它只在某些时候匹配——每秒钟一次。所以我创建了这个问题的最小工作样本 我在Opera和Firefox中尝试了这段代码。两者的行为相同: >>> domainRegex = /(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/g; /(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/g >>> domainRegex.exec('mail-we0-f174.go

我定义一个regex对象,然后在循环中匹配它。准确地说,它只在某些时候匹配——每秒钟一次。所以我创建了这个问题的最小工作样本

我在Opera和Firefox中尝试了这段代码。两者的行为相同:

>>> domainRegex = /(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/g;
/(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/g 
>>> domainRegex.exec('mail-we0-f174.google.com');
Array [".google.com", "google.com"]
>>> domainRegex.exec('mail-we0-f174.google.com');
null
>>> domainRegex.exec('mail-we0-f174.google.com');
Array [".google.com", "google.com"]
>>> domainRegex.exec('mail-we0-f174.google.com');
null
>>> domainRegex.exec('mail-we0-f174.google.com');
Array [".google.com", "google.com"]
>>> domainRegex.exec('mail-we0-f174.google.com');
null
为什么会这样?这种行为有记录吗?除了在循环体内部定义正则表达式之外,还有其他方法吗?

按照您描述的方式工作;当存在
/g
修饰符时,它将返回一个匹配项,从每次调用开始,直到不再有匹配项为止,此时它返回
null
,并且
lastIndex
的值重置为0

但是,由于您已使用
$
锚定表达式,因此不会有多个匹配项,因此您可以改为使用并丢失
/g
修饰符:

var domainRegex = /(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/;
'mail-we0-f174.google.com'.match(domainRegex); // [".google.com", "google.com"]

每次运行正则表达式的exec方法时,都会得到下一个匹配项

一旦到达字符串末尾,它将返回
null
,让您知道您已获得所有匹配项。下一次,它又从头开始

由于只有一个匹配项(返回完整匹配项和括号中的匹配项的数组),第一次,正则表达式从一开始就开始搜索。它找到匹配项并返回。下一次,它到达末尾并返回null。因此,如果在循环中有此项,则可以执行类似的操作来循环所有匹配项:

while(regExpression.exec(string)){
    // do something
}
然后下一次,它再次从位置0开始

“有办法吗?”


如果您知道只有一个匹配项,或者您只需要第一个匹配项,那么可以将te结果保存到变量中。无需恢复
.exec
。如果您对所有的匹配都感兴趣,那么您需要继续进行,直到得到
null

为什么不使用简单的匹配方法来进行类似字符串的匹配呢

'mail-we0-f174.google.com'.match(/(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/)

使用
RegExp
执行全局搜索时,exec方法从开始匹配 这个
lastIndex
属性在每次
exec
调用和 设置为上次找到匹配项后的位置。如果匹配失败,lastIndex将重置为0,这将导致
exec
从一开始就再次匹配

var a = 'asdfeeeasdfeedxasdf'
undefined
var p = /asdf/g
p.lastIndex
4
p.exec(a)
["asdf"]
p.lastIndex
11
p.exec(a)
["asdf"]
p.lastIndex
19
p.exec(a)
null //match failed
p.lastIndex
0 //lastIndex reset. next match will start at the beginning of the string a

p.exec(a)
["asdf"]
回复的其他信息:

您还可以设置

或者只是为每次执行创建一个新的正则表达式,我发现它更干净

new RegExp(myRgx).exec(someString);

这可能与@GDR重复,因为(请阅读“描述”部分)。@Jack我认为相关问题的答案是相同的?@Ozzy解释了为什么会这样,但不同的答案是,方法是错误的:)因为在循环的每次迭代中创建一个新的Regex对象实例的性能很差。除非您需要分配它,否则您永远无法使用该值<代码>while((match=myRe.exec(str))!==null){
new RegExp(myRgx).exec(someString);