什么时候应该使用正则表达式回溯控件,例如 (*PRUNE)?
Posted
技术标签:
【中文标题】什么时候应该使用正则表达式回溯控件,例如 (*PRUNE)?【英文标题】:When should regex backtracking controls, like (*PRUNE), be used? 【发布时间】:2016-03-23 16:50:25 【问题描述】:一些正则表达式引擎支持与回溯相关的动词:(*PRUNE)
、(*SKIP)
、(?doSomeCode();)
* 等。我已经知道这些动词的作用,来自Reference - What does this regex mean?。
我倾向于认为这些动词有些深奥,或者至少对于更底层的编程类型来说是不必要的步骤。与其需要(*PRUNE)
,不如在幕后进行更多优化(例如在编译器或引擎中)(降低正则表达式编写器/程序员和读取器的复杂性)?
那么,在实践中,在什么情况下在正则表达式中包含与回溯相关的动词是有用的?这样做有什么好处吗?
*
虽然在技术上不是回溯控制动词,但许多在正则表达式中执行任意代码的示例都以影响回溯或受回溯影响的方式执行此操作。
背景
这些功能最初是实验性的,尽管它们在 the Perl regex tutorial 中不再被标记。难怪我无法在 Internet 上找到很多关于这些结构的信息(尤其是当搜索被代码之外的 skip
或 prune
的不相关结果阻塞时)。我敢打赌,有很多人在正则表达式方面足够先进,可以使用这些根本不了解它们的动词。
因此存在许多阻碍广泛使用的实际障碍:
-
功能是实验性的
功能不明确
功能先进
试图找到一个超越这一点的答案并找到一个好的用例,或者从创建这些功能的开发人员那里找到推理。
我也知道存在类似的closed (too opinion-based) question,但它没有回答我的问题,因为对该问题说“是”的唯一答案给出了两个链接,其中一个是深奥的用途(另外,我不明白...)。另一个虽然给出了何时使用(*FAIL)
的情况,但没有解决我提到的任何其他构造,也没有使用(*FAIL)
作为回溯机制。据我了解,(*FAIL)
可以被any regex that always fails 模拟。
让我重新指定我在答案中寻找的内容:
与回溯特别相关 非深奥 实用 不仅仅是一个使用示例 对给出的任何示例都有解释 可能包括添加功能原因的背景信息 可能包括与未来功能相关的更新及来源(Perl 或其他正则表达式风格)【问题讨论】:
Have you used the Perl 5.10 backtracking control verbs in your regexes yet?的可能重复 我看不出这个问题(“那么,在什么情况下在正则表达式中包含与回溯相关的动词有用,实际上?”)与链接的不同,并且正确地关闭一(“你在你的正则表达式中使用过 Perl 5.10 回溯控制动词吗?它们帮助你[解决]了哪些问题?”) @miken32 我更新了我的问题,更详细地解释了为什么它没有回答问题。现在是否清楚我的要求有何不同?我不是在问只是的例子。 Rexegg 有一个tutorial worth reading。最常用的实用动词可能是(*SKIP)(*FAIL)
or (*SKIP)(*F)
together with this trick。例如,假设您想匹配is
(如果不在括号内)。里面的内容可以是skipped by use of these verbs (demo)。
【参考方案1】:
您可以查看的一个很好的文档是section about directives in Parse::RecDescent。尤其是 <commit>
指令,似乎与 (*PRUNE)
有某种关联(尽管也有 (*COMMIT)
),并且包含一个有启发性的示例。
我个人的印象是,大多数时候它们为您提供了使您的正则表达式更好的工具(例如,性能更好或更清晰),但不一定更有效。举个例子,你可能没有(*PRUNE)
,但你会遭受更重的回溯,这对你的影响取决于你试图匹配的内容。回复(*FAIL)
,它可能会被一个不匹配的子正则表达式模拟,但它的意图更清楚,它至少增强了可读性。
【讨论】:
链接的材料是否使用 Perl 6 正则表达式?我对 Perl 6 正则表达式不是很熟悉,尽管它看起来更类似于 BNF。 (自从我最初问这个 q 以来,我学到了很多东西,但我仍然不知道bless
,例如,在 Perl 中做了什么。)
不,该链接指的是一个可追溯到 5.6.2 matrix.cpantesters.org/?dist=Parse-RecDescent+1.967013 的 Perl 5 模块 - 该链接旨在为您提供一个示例,说明在何处修剪搜索空间可能有意义无论如何。【参考方案2】:
简而言之:您会知道是否需要使用它们,如果不确定,请不要使用。
正如其他人所暗示的那样,这些往往是适合语法处理的基于性能的优化工具。过早的优化不仅是万恶之源,这些功能直到最近才被标记为实验性的。因此,人们可能会合理地推断出它们对于大多数用例来说不是必需的,并且除非必要,否则最好不要借用麻烦/复杂性。
【讨论】:
以上是关于什么时候应该使用正则表达式回溯控件,例如 (*PRUNE)?的主要内容,如果未能解决你的问题,请参考以下文章