对于初学者编写正则表达式而言,这似乎是一个巨大的混乱源,可能会导致隐藏的性能问题,并且看起来典型的用例将是非贪婪的。
这仅仅是出于遗留原因(它是如何首次完成的,每个实现都会复制它),还是有理由呢?
答案 0 :(得分:10)
部分答案可能涉及RE在实际计算中的起源。它们原来是theoretical concept from automata theory and formal language theory,直到Ken Thompson himself编写了一个真实的实现,并在qed和ed(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闭包算子(星);对于正则表达式中的其他所有内容,最长匹配与最短匹配相同。
当你从这些角度思考它时,你会发现更现代的工具意识到你需要两者。我迟到了所以我只想到两个例子:
ksh
和bash
都提供了大多数特殊变量修改运算符的“最长匹配”和“最短匹配”形式。
Lua正则表达式包含*
表示Kleene闭包最长匹配,-
表示Kleene闭包最短匹配。当我忘记逃避文字-
符号时,这个人总是咬我。
回到Kleene的原创作品并看看是否可能影响早期工具的最长匹配将会很有趣。
答案 5 :(得分:1)
似乎典型的用例不会贪婪。
我想明确指出这是错误的,除非“典型用例”意味着HTML黑客攻击。
一个简单的例子是用于编程语言的词法分析器。你根本不想要
foo = 42
被解释为3个变量,后跟一个等号,后跟2个数字。相反,通常您希望解析器考虑最长的匹配。
在HTML出现之前,我们的老年人已经用贪婪的正则表达式生活了几十年,我们做得很好。即使在今天,我仍然不会在99%的情况下使用非贪婪的,不可否认的是因为我懒得查找语法,但也因为很少你不能只写一个被终止的贪婪的人。例如,匹配字符串:
"(\\"|[^"])*"