对于编写正则表达式的初学者来说,这似乎是一个巨大的困惑源,可能会导致隐藏的性能问题,而且典型的用例似乎是非贪婪的。
这仅仅是出于遗留原因(这是它最初是如何完成的,并且每个实现都复制它),还是有它的原因?
对于编写正则表达式的初学者来说,这似乎是一个巨大的困惑源,可能会导致隐藏的性能问题,而且典型的用例似乎是非贪婪的。
这仅仅是出于遗留原因(这是它最初是如何完成的,并且每个实现都复制它),还是有它的原因?
部分答案可能涉及实际计算中 RE 的起源。它们最初是自动机理论和形式语言理论的理论概念,直到Ken Thompson 自己编写了一个真正的实现并在qed和ed(1)中使用它们。
原始版本只有贪婪的语法,所以甚至没有做出决定。
在性能方面,由于回溯,惰性量词并不总是更快:http: //blog.stevenlevithan.com/archives/greedy-lazy-performance
至于实际设计,老实说,我不能说为什么量词默认是贪婪的,但我确实想知道使用什么控制字符来使量词变得贪婪而不是懒惰。我不认为?
会削减它:-)
可能的原因:如果它不是贪婪的,正则表达式引擎需要回溯很多。
嗯,重要的是,计算机尽可能以可预测的方式运行。所以正确的行为应该遵循一个简单的规则,比如贪心匹配,这样至少有经验的程序员可以预测一段代码的结果。
至于一个典型的用例是否应该是非贪婪的,那么以下情况呢:假设我有一个包含 foo1909、bar3939、baz3331 等条目的文件,我只想提取这些数字。将 (\d*) 写为正则表达式似乎很自然。
你可能会说写 (\d*)\D 之类的一样容易,但基本上总是这样,程序员可以更明确,更少含糊。因为我们想要一个 100% 可预测的默认行为,并且在头脑中计算起来很简单,所以这对我来说似乎是合理的。
这里真正的问题是 Kleene 闭包运算符(星号);对于正则表达式中的其他所有内容,最长匹配与最短匹配相同。
当您从这些方面考虑时,您会意识到更现代的工具会意识到您两者都需要。我迟到了,所以我只能想到两个例子:
两者都ksh
提供大多数特殊变量更改运算符的bash
“最长匹配”和“最短匹配”形式。
Lua 正则表达式包括*
Kleene 闭包最长匹配和-
Kleene 闭包最短匹配。-
当我忘记逃避文字符号时,这个总是咬我。
回到 Kleene 的原始工作,看看这是否会影响早期的最长匹配工具会很有趣。
一个典型的用例似乎是非贪婪的。
我想明确指出这是错误的,除非“典型用例”意味着 HTML 黑客。
一个简单的例子是编程语言的词法分析器。你根本不想要
foo = 42
被解释为 3 个变量,后跟等号,后跟 2 个数字。相反,通常您希望解析器考虑最长的匹配项。
在 HTML 出现之前,我们这些年长的人已经用贪婪的正则表达式生活了几十年,我们做得很好。即使在今天,我在 99% 的情况下都不会使用非贪婪的,诚然是因为我懒得查找语法,但也因为在很少的情况下你不能只写一个终止良好的贪婪。例如,要匹配一个字符串:
"(\\"|[^"])*"