正则表达式的“贪婪”如何运作

时间:2014-03-07 04:33:14

标签: regex

这是一个非常简单的正则表达式: -

kabk
k(.*)k
result:
kabk has 1 group:
ab

我通常做的是以下,这是正确但不必要的。

k([^k]*)k

任何人都可以向我解释正则表达式解析器是如何工作的吗?是.*应该尽可能多地消费。

4 个答案:

答案 0 :(得分:2)

是的,*运算符为greedy,并且会捕获尽可能多的有效字符。

例如,应用于k(.*)k的模式kkkkak将捕获kkka

您可以使用?运算符使运算符非贪婪。

因此应用于k(.*?)k的模式kkkkak将捕获 nothing ,因为最小的非贪婪匹配是在前两个k个字符之间不允许任何内容

在回复您的评论时,模式中最终k的存在意味着在尽可能多地消费之后,它需要尽可能多地留下以匹配k

答案 1 :(得分:2)

让我们首先在regex101.com调试器上看k([^k]*)k(使用否定匹配)::

1   /k([^k]*)k/ kabk
2   /k([^k]*)k/ kabk
3   /k([^k]*)k/ kabk
4   /k([^k]*)k/ kabk
5   /k([^k]*)k/ kabk
6   /k([^k]*)k/ kabk
7   /k([^k]*)k/ kabk
#   Match found in 7 steps.

现在让我们在同一个regex101.com调试器上看k(.*)k(使用geedy匹配进行匹配):

1   /k(.*)k/ kabk
2   /k(.*)k/ kabk
3   /k(.*)k/ kabk
4   /k(.*)k/ kabk
5   /k(.*)k/ kabk
6   /k(.*)k/ kabk BACKTRACK
7   /k(.*)k/ kabk BACKTRACK
8   /k(.*)k/ kabk
9   /k(.*)k/ kabk
#   Match found in 9 steps.

显然,第一个正则表达式在较长的字符串中效率更高,因为不涉及BACKTRACK。

答案 2 :(得分:1)

kabk中,只有两个k。因此,了解贪婪的比赛并不是一个恰当的例子。

让我们尝试不同的例子:kabkxyk

贪婪版本匹配返回kabkxyk.*在最后k之前前进):(跟随是javascript):

'kabkxyk'.match(/k.*k/)
// ["kabkxyk"]

非贪婪版本匹配返回kabk

'kabkxyk'.match(/k.*?k/)
// ["kabk"]

答案 3 :(得分:0)

是的,.*是贪婪的。它尽可能匹配。

.*?非贪婪或吝啬。它匹配尽可能少。

如果您将“香蕉”与ba.*a相匹配,则会与banana匹配。

如果您将“香蕉”与ba.*?a相匹配,则会与bana匹配。