Dan*_*nez 5 javascript regex actionscript-3 capturing-group ecmascript-5
我有两种不同语言的正则表达式,它们产生相同的奇数结果(javaScript和Flash).我想知道的不是如何解决它,而是为什么会发生这种行为?
正则表达式:
\[(\\{2}|\\\]|[^\]])*\]
Run Code Online (Sandbox Code Playgroud)
这里的目标是匹配一个括号中的字符串,并确保我不会停留在转义括号中.
如果我有文本输入[abcdefg]它是正确匹配的,但作为捕获组的一部分返回的唯一内容是g,在我期望的位置abcdefg.如果我将表达式更改为
\[((?:\\{2}|\\\]|[^\]])*)\],那么我得到我想要的结果.
那为什么会这样呢?这会在其他语言中保持一致吗?
注意:简化表达式以\[([^\]])*\]产生相同的问题.
无论出现什么问题,ActionScript和JavaScript都应该产生相同的结果,因为它们都实现ECMAScript(或其超集,但对于正则表达式,它们不应该不同意).
但是,是的,这将发生在任何语言(或更确切地说任何正则表达式).原因是您正在重复捕获组.让我们来简单的例子:匹配(.)*反对abc.所以我们重复的是(.).它第一次试图,发动机进组,火柴a用.,离开团的捕捉a.只有现在,量词才会启动并重复整个过程.所以我们再次进入该组,并匹配并捕获b.此捕获将覆盖前一个捕获,因此\1现在包含b.第三次重复再次相同:捕获将被覆盖c.
我不知道行为不同的正则表达式风格,并且唯一允许您访问所有先前捕获(而不是仅覆盖它们)的是.NET.
解决方案是提出的一个pswg.进行重复非捕获所需的分组(这将提高性能,因为您无需进行所有捕获和覆盖)并将整个事物包装在一个新组中.你的表达式有一个小缺陷:你需要在否定的字符类中包含反斜杠.否则,回溯可以给你一个匹配[abc\].所以这里有一个表达式可以按预期工作:
\[((?:\\{2}|\\\]|[^\]\\])*)\]
Run Code Online (Sandbox Code Playgroud)
工作演示.(不幸的是,它没有显示捕获,但它表明它在所有情况下都给出了正确的匹配)
请注意,您的表达式不允许其他转义序列.特别是单个\,后跟除了a之外的任何东西]都会导致你的模式失败.如果这不是你想要的,你可以使用:
\[((?:\\.|[^\]\\])*)\]
Run Code Online (Sandbox Code Playgroud)
使用"展开循环"技术可以进一步提高性能:
\[([^\]\\]*(?:\\.[^\]\\]*)*)\]
Run Code Online (Sandbox Code Playgroud)