Answers:
这是贪婪和非贪婪量词之间的区别。
考虑输入101000000000100
。
使用1.*1
,*
是贪婪的-它会一直匹配到最后,然后回溯直到可以匹配为止1
,剩下的就是您1010000000001
。
.*?
是非贪婪的。*
将不匹配任何内容,但随后将尝试匹配多余的字符,直到匹配为止1
,最终匹配101
。
所有的量词有一个非贪婪模式:.*?
,.+?
,.{2,6}?
,甚至.??
。
在你的情况下,类似的模式可能是<([^>]*)>
-匹配任何东西,但一个大于号(严格来说,它的其他零个或多个字符匹配比>
在中间<
和>
)。
请参阅量化器备忘单。
?
与非贪婪??
有何不同的示例?
"abc"
,正则表达式/\w\w?\w/
将匹配完整的字符串"abc"
-因为它?
很贪心。/\w\w??\w/
很懒-它只会匹配"ab"
。"abc"
如果稍后失败,它将仅回溯并匹配。
默认情况下,正则表达式中的重复是贪婪的:他们尝试匹配尽可能多的代表,而当这不起作用并且必须回溯时,他们尝试一次匹配更少的代表,直到匹配整个模式为止找到了。结果,当匹配最终发生时,贪婪的重复将匹配尽可能多的重复。
该?
作为的重复数量更改此行为成为非贪婪,也被称为不愿(在例如,Java)(有时候“懒”)。相比之下,此重复将首先尝试匹配尽可能少的代表,并且当此重复不起作用并且必须回溯时,他们将开始每次匹配一个代表。结果,当比赛最终发生时,勉强的重复将匹配尽可能少的次数。
让我们比较一下这两种模式:A.*Z
和A.*?Z
。
给出以下输入:
eeeAiiZuuuuAoooZeeee
模式产生以下匹配:
A.*Z
产生1个匹配:AiiZuuuuAoooZ
(见rubular.com)A.*?Z
产生2个匹配项:AiiZ
和AoooZ
(请参见rubular.com)让我们首先关注什么A.*Z
。当它匹配的第一个A
,在.*
,贪婪,首先尝试匹配尽可能多.
地。
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
由于Z
不匹配,因此引擎会回溯,然后.*
必须少匹配一个.
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
这又发生了几次,直到最后我们来到这里:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
现在Z
可以匹配,因此总体模式匹配:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
相比之下,在A.*?Z
最初的匹配中,勉强重复的次数.
越少越好,然后.
根据需要进行更多的重复。这解释了为什么它在输入中找到两个匹配项。
这是两种模式匹配的直观表示:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
在许多应用中,上面的输入中的两个匹配是所希望的,因此使用了一个不情愿.*?
而不是贪婪的方法.*
来防止过度匹配。但是,对于这种特定模式,使用否定字符类是更好的选择。
该模式A[^Z]*Z
还找到与A.*?Z
上述输入的模式相同的两个匹配项(如ideone.com所示)。[^Z]
是所谓的否定字符类:它除了匹配任何东西Z
。
两种模式之间的主要区别在于性能:更严格地说,否定的字符类只能为给定输入匹配一种方式。对这个模式使用贪婪或勉强的修饰符都没关系。实际上,在某些情况下,您甚至可以做得更好,并使用所谓的所有格量词,它根本不会回溯。
这个例子应该是说明性的:它显示了在相同的输入下,贪婪的,不情愿的和否定的字符类模式如何不同地匹配。
eeAiiZooAuuZZeeeZZfff
这些是上述输入的匹配项:
A[^Z]*ZZ
产生1个匹配:AuuZZ
(上ideone.com所见)A.*?ZZ
产生1个匹配:AiiZooAuuZZ
(上ideone.com所见)A.*ZZ
产生1个匹配:AiiZooAuuZZeeeZZ
(上ideone.com所见)这是它们匹配内容的直观表示:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
这些是指向stackoverflow的问题和解答的链接,这些问题和解答涵盖了可能感兴趣的一些主题。