24

我正在定义一个正则表达式对象,然后在循环中匹配它。准确地说,它有时只匹配 - 每隔一段时间。所以我创建了这个问题的最小工作样本。

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

为什么会这样?这种行为是否记录在案?除了在循环体内定义正则表达式之外,还有其他方法吗?

4

5 回答 5

23

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

但是,由于您使用的锚定表达式$不会超过一个匹配项,因此您可以String.match()改用并丢失/g修饰符:

var domainRegex = /(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/;
'mail-we0-f174.google.com'.match(domainRegex); // [".google.com", "google.com"]
于 2013-08-27T10:23:39.697 回答
4

Ja͢cks回复的附加信息:

您还可以设置lastIndex

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

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

new RegExp(myRgx).exec(someString);
于 2017-01-11T12:59:14.403 回答
3

使用 a 执行全局搜索时,exec 方法从lastIndex 属性RegExp开始匹配。该属性在每次调用时设置,并设置为找到的最后一个匹配项之后的位置。如果匹配失败, lastIndex 将重置为0,这会导致重新从头开始匹配。lastIndexexecexec

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"]
于 2013-08-27T10:34:26.320 回答
2

每次您运行正则表达式的 exec 方法时,它都会为您提供下一场比赛。

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

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

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

然后下一次,它又从位置 0 开始。

“有办法吗?”

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

于 2013-08-27T10:26:50.660 回答
0

为什么不对字符串使用简单的匹配方法

'mail-we0-f174.google.com'.match(/(?:\.|^)([a-z0-9\-]+\.[a-z0-9\-]+)$/)
于 2013-08-27T10:29:43.040 回答