Javascript - 多行正则表达式 : lastIndex stuck on newlines?

标签 javascript regex

一些背景

来自 Javascript: The Definitive Guide :

When regexp is a global regular expression, however, exec() behaves in a slightly more complex way. It begins searching string at the character position specified by the lastIndex preperty of regexp. When it finds a match, it sets lastIndex to the position of the first character after the match.

我认为任何经常使用 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

RegExp 似乎卡在第二行并且不会增加 lastIndex 属性。这似乎与The Rhino Book矛盾.如果我自己按如下方式设置它,它会继续并最终按预期返回 null,但似乎我不必这样做。

>> rx.lastIndex = 5
5
>> rx.exec(tx)
[bar,bar]
>> rx.lastIndex
8
>> rx.exec(tx)
null

结论

显然,只要匹配项为空字符串,我就可以递增 lastIndex 属性。但是,作为好奇的类型,我想知道为什么 exec 方法不增加它。为什么不是呢?

注意事项

我在 Chrome 和 Firefox 中观察到了这种行为。它似乎只有在有相邻的换行符时才会发生。

[编辑]

Tomalak下面说把pattern改成/^(.+)$/gm会导致表达式不会卡住,但是空行会被忽略。可以更改它以仍然匹配该行吗?谢谢解答Tomalak !

[编辑]

使用以下模式并使用第 1 组适用于我能想到的所有字符串。再次感谢Tomalak .

/^(.*)((\r\n|\r|\n)|$)/gm

[编辑]

先前的模式返回空行。但是,如果您不关心空行,Tomalak给出了以下解决方案,我认为它更清晰。

/^(.*)[\r\n]*/gm

[编辑]

前两个解决方案都会卡在尾随换行符处,因此您必须去除它们或手动增加 lastIndex

[编辑]

我在 Flagrant Badassery 找到了一篇详细介绍 lastIndex 跨浏览器问题的好文章.除了很棒的博客名称外,这篇文章还让我对这个问题有了更深入的了解,并提供了一个很好的跨浏览器解决方案。解决方法如下:

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;
    }
}

最佳答案

问题是点在

^(.*)$

不匹配换行符,但是使用 "m" 开关可以使 "^""$" 锚定到新行行字符。也就是说"\n""\n"之间的"nothing"可以和"(.*)"匹配成功。

由于此匹配项的宽度为零,因此 lastIndex 属性无法前进。尝试:

^(.+)$

编辑:要匹配空白行,请执行以下操作:

^(.*)\n?     // remove all \r characters beforehand

^(.*)(?:\r\n|\n\r|\n|\r)?  // all possible CR/LF combinations, but *once* at most

...然后只去匹配组 1。

关于Javascript - 多行正则表达式 : lastIndex stuck on newlines?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/381214/

相关文章:

javascript - 如何根据文档执行与 vuejs 插槽通常执行的操作相反的操作?

javascript - ASYNC AWAIT 内的 While 循环

javascript - document.writeln 不写入新行

Javascript - 获取文本区域中的所有网址

javascript - 修复在滚动页面中显示隐藏面板

javascript - 413 请求实体太大 HighCharts

regex - 如何在谷歌表格公式中提取精确的 10 位 ISBN10

c# - 如果术语在搜索文本中被换行符打断,我如何使用 RegEx 查找术语

node.js - 如何正则表达式将使用 "++++"、 "+++"作为组分隔符的文本输入文件转换为 CSV 或 JSON

iphone - 带大括号的正则表达式