Perl兼容的正则表达式引擎:如何实现?

时间:2018-06-22 07:57:43

标签: java python regex perl parsing

perl,python,java和vim等使用正则表达式进行解析的基本方法是什么?

不是聪明的形式语言方法(即NFADFA);解析器组合器(例如14 line regex engine)。

我看过Java实现perl样式正则表达式的源代码,但是其复杂的功能(例如,反向引用)和效率(例如,Boyer-Moore子字符串匹配)使我们很难看清它如何< em>基本上有效。

编辑 各种资料都说涉及“回溯”(例如Regular Expression Matching Can Be Simple And Fast正规方法课程),但不清楚在到底是什么回溯...是吗?一种评估NFA的方法?可以直接从正则表达式的AST完成吗?

java / perl / python regex引擎实际上做什么?

是否是这样的:“一种以常规语言生成所有可能单词的方法,但是一旦它与输入字符串不匹配,就放弃特定单词”。

2 个答案:

答案 0 :(得分:7)

正则表达式引擎中有两种通用方法。

  • 正则表达式可以转换为有限自动机。这种关系在计算机科学中得到了很好的研究。这些有限的自动化然后可以有效地执行,甚至向后运行。它们提供了有力的保证,例如在线性时间和关于输入字符串的恒定空间中运行,但是从正则表达式创建有限自动机可能会很昂贵。这种方法还将引擎限制为真正的正则表达式,即排除了诸如反向引用或递归之类的高级功能。

  • 正则表达式可以由回溯引擎解释。如果模式中的替代方法失败,则可以追溯到最后一个决策点,然后尝试其他方法。这是非常灵活的,并且(具有递归+命名子模式等额外功能)可以解析更大种类的形式语言(形式上像LL(*)语法集之类的东西)。这与PEG解析器非常相似。最大的缺点:由于回溯,即使没有任何其他高级功能,运行正则表达式也可能花费大量时间。

最重要的是,正则表达式引擎具有额外的优化功能,例如首先在模式中搜索常量子字符串,因为它比运行任何类型的正则表达式(任何人甚至都可以使用矢量化CPU指令)更高效。如果在多个常量字符串之间有一个选择点,则可以很容易地将它们编译成trie数据结构(实际上是一个简单的有限自动机)。这样可以减少回溯的次数。

证明a*a*a*a*a*b模式是字符串aaaaaaaaaaaaaaacb上的正则表达式,它证明了有限自动机和回溯之间的区别。有限的自动机可以很容易地看到由于输入中的c,该模式将不匹配。但是,回溯引擎现在具有许多决策点,可以在其中为每个a*子模式尝试不同的长度。在这种情况下,像Perl或Python中的re模块这样的正则表达式引擎将呈指数级增长,即完成需要花费很长时间–向输入中添加更多a可以使其花费更长的时间。如果不受信任的用户可以提供任意正则表达式,则可以进行有趣的拒绝服务攻击。对于不受信任的输入,仅应使用基于有限自动机的正则表达式引擎,例如来自Google的RE2。

答案 1 :(得分:3)

Perl 2中的正则表达式来自Henry Spencer

regexp.c仅有两千行,并不比具有更多功能的更高版本困难。