因为“一个+ ?“是懒惰的,为什么“a+?”匹配“aaab"

Since "a+?" is Lazy, Why does "a+?b" Match "aaab"?

本文关键字:为什么 匹配 aaab quot 一个 因为 是懒惰的      更新时间:2023-09-26

在使用 javascript: The Definitive Guide学习javascript正则表达式时,我被下面这段话弄糊涂了:

但/+吗?/匹配字母a的一次或多次出现,匹配为必要时少写几个字。当应用于同一个字符串时,this模式只匹配第一个字母a。

现在让我们使用非贪婪版本:/a+?b/。这应该与字母b前面有尽可能少的a。当应用对于同一个字符串" aaab ",您可能希望它只匹配一个a和最后一个字母b。然而,事实上,这种模式匹配整个字符串,就像模式的贪心版本。

为什么会这样?

这是书上的解释:

这是因为正则表达式模式匹配是通过查找完成的字符串中第一个可能匹配的位置。自的第一个字符开始匹配字符串,从后续字符开始的较短匹配永远不会甚至考虑。

我不明白。有人能给我一个更详细的解释吗?

好了,你有了搜索空间"aaabc"和模式/a+?b/

/+吗?B/match "a"?没有。

/+吗?B/匹配"aa"?没有。

/+吗?B/匹配"aaa"?没有。

/+吗?B/匹配"aaab"?是的。

由于您匹配的是文字字符而不是任何类型的通配符,因此正则表达式a+?b实际上与a+b是相同的。两者都能匹配的唯一序列类型是一个或多个a字符后跟一个b字符的字符串。非贪婪修饰符在这里没有区别,因为a唯一可能匹配的是a

当非贪婪限定符应用于可以取很多不同值的东西时,就变得有趣了,比如.。(edit或者像a+?这样左边有有趣的东西的情况)

编辑本;如果您期望a+?baaab中的b之前匹配最后一个a,那么它不是这样工作的。在字符串中搜索模式隐含地意味着搜索该模式最早出现的时间。因此,尽管从最后一个a开始确实给出了匹配模式的子字符串,但它不是匹配的第一个子字符串。

引擎在字符串开头尝试匹配

谁能给我一个更详细的解释?

是的。

简而言之:.+?不会在整个字符串的级别上全局查找最短匹配,而是在局部查找,从字符串中引擎当前所在的位置开始查找。

引擎如何工作

当您对字符串aaab尝试正则表达式时,引擎首先尝试从字符串中的第一个位置开始查找匹配。该位置是第一个a之前的位置。如果引擎无法在第一个位置找到匹配,则继续从第二个位置(在第一个和第二个a之间)开始再次尝试

那么可以通过正则表达式a+?b在第一个位置找到匹配吗?是的。

    a匹配第一个a
  • +?量词告诉引擎匹配所需的最少数量的a字符。由于我们希望返回匹配,必需意味着必须允许以下令牌(在本例中)匹配。在这种情况下,允许b匹配所需的a字符的最少数量是所有剩余的a字符。
  • b matches

在细节中,第二点有点复杂(引擎试图将b与第二个a匹配,失败,回溯…),但您不需要担心。

'?+后面的'表示满足表达式的最小字符数。/a+/表示在其他字符前面可以遇到的一个或多个'a'。为了满足/a+?/(因为它不贪婪)它只需要一个'a'。

为了满足/a+?B/,因为我们在末尾有' B ',为了满足这个表达式,它需要在碰到' B '之前匹配一个或多个'a'。它必须碰到'b'。/a+/不需要碰到b,因为RegEx不要求这样做。/+ ?B/必须按那个' B '。

想想看。a+还有别的意思吗?B/本来可以?

希望能有所帮助