为什么不创建反向引用?

Exp*_*lls 4 regex backreference

我理解将?:正则表达式括号的开头放在内部将阻止它创建一个应该更快的反向引用.我的问题是,为什么这样做?速度是否足够明显以保证这一考虑?在什么情况下它会如此重要,以至于每次你不打算使用它时都需要仔细跳过反向引用.另一个缺点是它使正则表达式更难阅读,编辑和更新(如果你最后想要使用反向引用).

总而言之,为什么不打算不创建反向引用呢?

Mik*_*uel 13

我认为你会混淆反馈\1和捕捉群体(...).

反向引用通过使语言非常规来阻止各种优化.

捕获组使正则表达式引擎做更多的工作来记住组的开始和结束位置,但不像后向引用那么糟糕.

http://www.regular-expressions.info/brackets.html详细解释了捕获组和对它们的引用.

编辑:

在使正则表达式非常规的反向引用上,请考虑以下与lua注释匹配的正则表达式:

/^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/
Run Code Online (Sandbox Code Playgroud)

所以--[[...]]是评论,--[=[...]=]是评论,--[==[...]==]是评论.您可以通过在方括号之间添加额外的等号来嵌套注释.

这不能通过严格的常规语言来匹配,因此简单的有限状态机无法在O(n)时间内处理它 - 您需要一个计数器.

Perl 5正则表达式可以使用反向引用来处理它.但是只要您需要非常规模式匹配,您的正则表达式库就必须放弃简单的状态机方法并使用更复杂,效率更低的代码.


Ala*_*ore 5

你是对的,表现并不是避免捕捉群体的唯一原因 - 事实上,这甚至不是最重要的原因.

另一个缺点是它使正则表达式更难阅读,编辑和更新(如果你最后想要使用反向引用).

我看它周围的其他方法:如果你习惯性地使用非捕获组,它更容易追踪在这些场合的一组数字,当你选择捕捉到的东西.本着同样的精神,如果你使用的命名组(假设你的正则表达式的味道支持他们),你应该总是使用命名组,并始终的名字给他们(在反向引用或替换字符串),而不是数量.遵循这些规则将至少部分地抵消非捕获组的可读性惩罚.

是的,PITA必须以这种方式混乱你的正则表达式,编写/维护正则表达式实现的人都知道它.在.NET中,您可以设置ExplicitCapture选项,将所有"裸"括号视为非捕获组,仅捕获命名组.在Perl 6中,括号(带或不带名称)总是捕获,方括号用于非捕获组.其他口味最终可能会效仿,但与此同时我们必须依靠良好的习惯.