为什么默认情况下正则表达式贪婪?

时间:2010-02-16 17:44:17

标签: regex language-design regex-greedy

对于初学者编写正则表达式而言,这似乎是一个巨大的混乱源,可能会导致隐藏的性能问题,并且看起来典型的用例将是非贪婪的。

这仅仅是出于遗留原因(它是如何首次完成的,每个实现都会复制它),还是有理由呢?

6 个答案:

答案 0 :(得分:10)

歇斯底里的Raisens


部分答案可能涉及RE在实际计算中的起源。它们原来是theoretical concept from automata theory and formal language theory,直到Ken Thompson himself编写了一个真实的实现,并在qeded(1)中使用它们。

原始版本只有贪婪的语法,所以甚至没有做出决定。

答案 1 :(得分:7)

在性能方面,由于回溯,延迟量词并不总是更快:http://blog.stevenlevithan.com/archives/greedy-lazy-performance

至于实际的设计,老实说,我不能说为什么量词在默认情况下是贪婪的,但我确实想知道什么样的控制字符会被用来使量词贪婪而不是懒惰。我认为?不会削减它: - )

答案 2 :(得分:5)

答案 3 :(得分:3)

嗯,重要的是计算机应尽可能预测。所以正确的行为应该遵循一个简单的规则,比如贪婪的匹配,这样至少有经验的程序员可以预测一段代码的结果。

至于典型用例是否应该是非贪婪的,请注意以下内容:假设我有一个包含foo1909,bar3939,baz3331等条目的文件,我只想提取这些数字。写(\ d *)作为正则表达式似乎很自然。

你可能会说它(/ d *)\ D或其他任何东西都很容易,但基本上总是这样,程序员可以更明确,更不明确。既然我们想要一个100%可预测的默认行为,并且在一个头脑中计算是微不足道的,那对我来说似乎是合理的。

答案 4 :(得分:3)

这里真正的问题是Kleene闭包算子(星);对于正则表达式中的其他所有内容,最长匹配与最短匹配相同。

当你从这些角度思考它时,你会发现更现代的工具意识到你需要两者。我迟到了所以我只想到两个例子:

  • kshbash都提供了大多数特殊变量修改运算符的“最长匹配”“最短匹配”形式。

  • Lua正则表达式包含*表示Kleene闭包最长匹配,-表示Kleene闭包最短匹配。当我忘记逃避文字-符号时,这个人总是咬我。

回到Kleene的原创作品并看看是否可能影响早期工具的最长匹配将会很有趣。

答案 5 :(得分:1)

  

似乎典型的用例不会贪婪。

我想明确指出这是错误的,除非“典型用例”意味着HTML黑客攻击。

一个简单的例子是用于编程语言的词法分析器。你根本不想要

foo = 42

被解释为3个变量,后跟一个等号,后跟2个数字。相反,通常您希望解析器考虑最长的匹配。

在HTML出现之前,我们的老年人已经用贪婪的正则表达式生活了几十年,我们做得很好。即使在今天,我仍然不会在99%的情况下使用非贪婪的,不可否认的是因为我懒得查找语法,但也因为很少你不能只写一个被终止的贪婪的人。例如,匹配字符串:

"(\\"|[^"])*"