来自Javascript:The Definitive Guide:
regexp但是,何时是全局正则表达式,exec()行为方式稍微复杂一些.它开始搜索string由lastIndexpreperty 指定的字符位置regexp.当找到匹配项时,它会设置lastIndex为匹配后第一个字符的位置.
我认为定期使用javascript RegExps的任何人都会认出这段话.但是,我在这个方法中发现了一个奇怪的行为.
请考虑以下代码:
>> rx = /^(.*)$/mg
>> tx = 'foo\n\nbar'
>> rx.exec(tx)
[foo,foo]
>> rx.lastIndex
3
>> rx.exec(tx)
[,]
>> rx.lastIndex
4
>> rx.exec(tx)
[,]
>> rx.lastIndex
4
>> rx.exec(tx)
[,]
>> rx.lastIndex
4
Run Code Online (Sandbox Code Playgroud)
RegExp似乎卡在第二行,并没有增加lastIndex属性.这似乎与犀牛书相矛盾.如果我自己设置如下,它继续并最终返回null按预期,但似乎我不应该.
>> rx.lastIndex = 5
5
>> rx.exec(tx)
[bar,bar]
>> rx.lastIndex
8
>> rx.exec(tx)
null
Run Code Online (Sandbox Code Playgroud)
显然,只要lastIndex匹配为空字符串,我就可以增加属性.然而,作为好奇的类型,我想知道为什么它不会被该exec方法增加.为什么不呢?
我在Chrome和Firefox中观察到了这种行为.它似乎只有在有相邻的换行符时才会发生.
Tomalak在下面说,改变模式/^(.+)$/gm将导致表达式不被卡住,但空行被忽略.这可以改为仍然匹配线?感谢Tomalak的答案!
使用以下模式并使用组1适用于我能想到的所有字符串.再次感谢Tomalak.
/^(.*)((\r\n|\r|\n)|$)/gm
Run Code Online (Sandbox Code Playgroud)
上一个模式返回空行.但是,如果您不关心空白行,Tomalak会给出以下解决方案,我认为该解决方案更清晰.
/^(.*)[\r\n]*/gm
Run Code Online (Sandbox Code Playgroud)
前两个解决方案都停留在尾随换行符上,因此您必须将它们剥离或lastIndex手动递增.
我发现了一篇很棒的文章,详细介绍lastIndex了Flagrant Badassery的跨浏览器问题.除了令人敬畏的博客名称,这篇文章让我对这个问题有了更深入的了解,并提供了一个很好的跨浏览器解决方案.解决方案如下:
var rx = /^/gm,
tx = 'A\nB\nC',
m;
while(m = rx.exec(tx)){
if(!m[0].length && rx.lastIndex > m.index){
--rx.lastIndex;
}
foo();
if(!m[0].length){
++rx.lastIndex;
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于点
^(.*)$
Run Code Online (Sandbox Code Playgroud)
与新行字符不匹配,但使用您的"m"开关制作"^"并"$"锚定到新行字符.这意味着之间的"一无所有" "\n",并"\n"可以与匹配成功"(.*)".
由于此匹配的宽度为零,因此该lastIndex属性无法前进.尝试:
^(.+)$
Run Code Online (Sandbox Code Playgroud)
编辑:要匹配空白行,请执行以下操作:
^(.*)\n? // remove all \r characters beforehand
Run Code Online (Sandbox Code Playgroud)
要么
^(.*)(?:\r\n|\n\r|\n|\r)? // all possible CR/LF combinations, but *once* at most
Run Code Online (Sandbox Code Playgroud)
......然后去比赛组1.