对于初学者编写正则表达式来说,这似乎是一个巨大的困惑源,可能会导致隐藏的性能问题,而典型的用例似乎应该是非贪婪的。
这只是出于传统原因(它最初是如此完成的,并且每个实现都复制了它),还是有其它原因呢?
对于初学者编写正则表达式来说,这似乎是一个巨大的困惑源,可能会导致隐藏的性能问题,而典型的用例似乎应该是非贪婪的。
这只是出于传统原因(它最初是如此完成的,并且每个实现都复制了它),还是有其它原因呢?
答案的一部分可能涉及正则表达式在实际计算中的起源。它们最初是从自动机理论和形式语言理论中的一个理论概念,直到Ken Thompson本人编写了真正的实现并在qed和ed(1)中使用它们。
最初版本只有贪婪语法,所以甚至没有需要做出的决定。
/x*/
可以匹配""、"x"或"xxx"(等等)。这种表达式定义了一个包括""、"x"和"xxx"在内的正则语言。请注意,这并没有涉及如何在文本中搜索匹配项;只有当你应用这个理论时,你才会关心贪婪性。 - Nate C-K就性能而言,因为会回溯,懒惰量词并不总是更快: http://blog.stevenlevithan.com/archives/greedy-lazy-performance
至于实际设计,我真的不知道为什么量词默认是贪婪的,但我确实想知道使用哪个控制字符来使量词变得贪婪而不是懒惰。我认为 ?
不够用 :-)
在可能的情况下,计算机的行为应该是可预测的。因此,正确的行为应该遵循一个简单的规则,比如贪婪匹配,这样至少有经验的程序员可以预测代码的结果。
至于典型用例是否应该是非贪婪的,那么以下情况怎么办:假设我有一个条目类似于foo1909,bar3939,baz3331的文件,并且我只想提取这些数字。使用(\d*)作为正则表达式似乎很自然。
你可能会说写(\d*)\D或其他方式同样容易,但通常情况下程序员可以更明确、更少歧义。由于我们希望默认行为是100%可预测的,并且可以轻松地在头脑中计算,所以我认为这很合理。
/foo|foobar/
和目标字符串 blahfoobarblah
,一个数学上纯粹的正则表达式总是匹配 foobar
,而 Perl 派生的 NFA 正则表达式将会匹配 foo
。 - Alan Moore看起来典型的使用情况应该是非贪婪的。
我想澄清一点,除非“典型的使用情况”指的是HTML黑客技巧,否则这是错误的。
编程语言的词法分析器就是一个简单的例子。你根本不希望
foo = 42
"(\\"|[^"])*"
/\*((?!\*/).)*\*/
与/\*.*?\*/
相比,后者更加简洁。随着分隔符数量的增加,情况会变得更糟,因为您必须否定所有分隔符。贪婪匹配在大多数情况下都可以正常工作,因为这些问题并不经常出现,但声称它有利于词法分析或者说它是错误的... - TrisT