【问题标题】:GNU grep and composite patternsGNU grep 和复合模式
【发布时间】:2017-02-06 15:46:20
【问题描述】:

我已阅读 why GNU grep is fast 以及 Boyer-Moore 的实现,但我真正想知道的是 grep 如何与 pat1|pat2 甚至 [ABC] 等复合模式一起工作。

grep 是在构建解析树吗?还是像检查简单模式列表一样检查复合模式?

到目前为止,我还没有找到任何解释它的合理网站。

我们将不胜感激快速解释和参考。

【问题讨论】:

  • 这里是参考:git.savannah.gnu.org/cgit/grep.git/tree 没有快速解释,不过 ;)
  • “解析树”是什么意思?
  • @rici 我的意思是类似于为 Aho-Corasick 算法构建的 trie。我知道这不是一个“死板”的定义,但我没有更好的词..
  • @VaultDweller:这是一个特里 :),这是一种树,可以肯定的是,但与解析几乎没有关系。如果您的意思是“grep 构造有限自动机吗?”,根据我的回答和链接的文章,答案是肯定的。

标签: regex parsing grep pattern-matching


【解决方案1】:

除了阅读代码,正如评论中所建议的那样,最好的起点是Russ Cox's interesting and readable essay 正则表达式匹配。 Russ 描述了构造 DFA(确定性有限自动机)的算法,并提到 grepawk 都使用该算法的变体。

这些实用程序的 Gnu 版本使用 Thompson's NFA construction algorithm 之类的东西构造 non-deterministic finite automaton (NFA),然后按照 Russ 的建议,懒惰地构造相应的 deterministic finite automaton (DFA),以避免 NFA->DFA 算法中潜在的指数爆炸。 powerset construction 算法的延迟执行不需要对该算法进行任何更改;它只是按需进行所需的计算,保留计算出的 powerset 的缓存。如果缓存大小超过某个限制,则会删除缓存条目以为新条目腾出空间。

GNU grep 还包括许多优化,旨在使其在实践中使用常见模式更快地工作,这些优化使代码相当复杂。然而,如果你想开始阅读源代码,你可以从 Gnulib 中的函数开始,用于 NFA->DFA 转换算法在dfa.c(函数dfaexec_main,它既可以通过 DFA 又可以按需计算新状态),以及文件regcomp.c(函数re_compile_internal)中的NFA构造。


既然在评论中提到过,我应该澄清一下,OP 所谓的“复合模式”实际上只是在其中一种伪装中使用交替运算符 | 的模式(包括可选运算符?,可以写成(...|)。和字符类,它们只是交替的紧凑表示,正如 Russ 在链接文章中指出的那样。)

“复合模式”还有另一种可能的含义,因为 grep 允许指定多个模式,或者通过多次使用 -e 命令行参数,或者通过使用 -f 选项从一个文件,每行一个。然后,Grep 对所有模式执行同时搜索,您可以将其视为复合搜索。但是,这实际上与简单的交替没有什么不同;在内部,grep 只是将所有选项连接到一个长正则表达式中,并在将其编译为单个 NFA 之前使用交替运算符进行标点。

【讨论】:

  • 可能值得一提的是,替代模式(OP 称它们为“复合模式”)每个都是通过状态机的路径。将这些路径分组并同时在各个组中逐步前进是在 DFA 中模拟 NFA 的技巧。直到阅读本文(谢谢!),我才意识到字符类实际上只是“交替的简洁表示”。呵呵。
  • @gregory:没有重写 Russ 的论文,我觉得我无法公正地描述 DFA、NFA 和 powerset 构造。我所知道的每一本解析/形式语言/编译器构造教科书以及散布在互联网上的无数讲义中也都有该材料。我根本不相信我有能力比所有这些人做得更好。我推荐人们参考 Russ 的文章,因为我认为他做得很好。也许有一天我会试一试......
  • .... 还请注意,重复运算符表示状态机中的一个循环,因此如果有一个循环,那么您将拥有无限数量的路径。子集构造(或现在维基百科所称的 powerset 构造)不会生成无限状态机,这是算法的一个重要方面。
  • @rici 感谢您的启发性解释!我知道 DFA 的创建,但转换为 NFA 是我缺失的环节。再次感谢!
猜你喜欢
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
相关资源
最近更新 更多