我有以下两种不同语言的正则表达式,它们产生相同的奇怪结果(javaScript 和 Flash)。我想知道的不是如何解决它,而是为什么会发生这种行为?
正则表达式:
\[(\\{2}|\\\]|[^\]])*\]
这里的目标是匹配括号内的字符串,并确保我不会停在转义括号处。
如果我有文本输入[abcdefg]
它是正确匹配的,但作为捕获组的一部分返回的唯一内容是g
,正如我所期望的那样abcdefg
。如果我将表达式更改为\[((?:\\{2}|\\\]|[^\]])*)\]
,然后我就得到了我想要的结果。
那么为什么会发生这种情况呢?这在其他语言中是否一致?
note:将表达式简化为\[([^\]])*\]
产生同样的问题。
不管问题如何,ActionScript 和 JavaScript 应该始终产生相同的结果,因为它们都实现了 ECMAScript(或其超集,但对于正则表达式,它们不应该不一致)。
但是,是的,这会发生在任何语言(或者更确切地说任何正则表达式风格)中。原因是您正在重复捕获组。让我们举一个更简单的例子:匹配(.)*
反对abc
。所以我们要重复的是(.)
。第一次尝试,引擎进入组,匹配a
with .
,离开该组并捕获a
。直到现在量词才开始起作用并重复整个过程。于是我们再次进组,匹配并捕获b
。此捕获会覆盖前一个捕获,因此\1
现在包含b
。第三次重复也是如此:捕获将被覆盖c
.
我不知道有什么行为不同的正则表达式风格,唯一可以让您访问所有以前的捕获(而不是仅仅覆盖它们)的是 .NET。
解决方案是 p.s.w.g.建议的。将重复所需的分组设置为非捕获(这将提高性能,因为您无论如何都不需要所有捕获和覆盖)并将整个内容包装在一个新组中。不过,您的表达式有一个小缺陷:您需要在否定字符类中包含反斜杠。否则,回溯可能会给你一个匹配[abc\]
。因此,这里有一个可以按您的预期工作的表达式:
\[((?:\\{2}|\\\]|[^\]\\])*)\]
(不幸的是,它没有显示捕获,但它表明它在所有情况下都给出了正确的匹配)
请注意,您的表达式不允许使用其他转义序列。特别是单个\
,后面跟着除了 a 以外的任何内容]
会导致你的模式失败。如果这不是您想要的,您可以使用:
\[((?:\\.|[^\]\\])*)\]
性能可以进一步提高“展开循环” https://stackoverflow.com/a/17043605/1633117技术:
\[([^\]\\]*(?:\\.[^\]\\]*)*)\]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)