2013-08-27 64 views
15

我正在定义一个正则表达式对象,然后在循环中匹配它。它只是偶尔匹配,确切地说 - 每隔两次。所以我创建了这个问题的最小工作示例。为什么Javascript正则表达式每次都匹配一次?

我在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 

为什么会发生这种情况?此行为是否记录在案?除了在循环体内定义正则表达式之外,有没有办法解决这个问题?

+3

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec# Finding_successive_matches – Passerby

+1

[为什么使用Javascript中的全局标志的RegExp会给出错误的结果?](http://stackoverflow.com/questions/1520800/why-regexp-with-global-flag-in-javascript-give-wrong-results ) – Bergi

+0

@GDR这是因为[RegExp.lastIndex]发生的(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex?redirectlocale=en-US&redirectslug=JavaScript %2FReference%2FGlobal_Objects%2FRegExp%2FlastIndex)(_ read“description”section_)。 –

回答

14

exec()以您描述的方式工作;本/g改性剂,它会返回一个比赛,从开始用lastIndex每次调用,直到有没有更多的比赛,此时它返回nulllastIndex值重置为0

但是,因为你有

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

每次运行你的正则表达式的exec方法它可以让你的下一场比赛时间:使用$不会有一个以上的比赛,所以你可以使用String.match()代替,失去了/g修改固定表达。

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

由于您只有一个匹配(它会返回完整匹配数组和从括号中的匹配项),第一次,正则表达式将从头开始搜索。它找到一个匹配并返回它。下一次,它会结束并返回null。所以,如果你有这样一个循环中,你可以通过所有的比赛做这样的事情循环:

while(regExpression.exec(string)){ 
    // do something 
} 

那么下一次,它再次从位置0

开始“有怎么办?“

那么,如果你知道只有一个匹配,或者你只想要第一个匹配,你可以将结果保存到一个变量。没有必要重复使用.exec。如果你对所有比赛感兴趣,那么你需要继续前进,直到你得到null

0

你为什么不使用简单的搭配方法字符串如

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

因为它具有不良的表现,创建一个循环的每次迭代的正则表达式对象的新实例。 – GDR

+0

@GDR谢谢你解释。 – dirtydexter

2

RegExp执行全局搜索时,exec方法开始于 的lastIndex property匹配开始。 lastIndex属性在每个exec调用处设置,并且 被设置为在找到的上次匹配之后的位置。如果匹配失败,lastIndex被重置为,这导致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"] 
0

附加信息来Ja͢cks响应:

您还可以设置lastIndex

var myRgx = /test/g; 
myRgx.exec(someString); 
myRgx.lastIndex = 0; 

或刚刚创建的每个执行,我觉得这更清洁的新的正则表达式

new RegExp(myRgx).exec(someString); 
相关问题