Logo
Section 1 / 4

贪心性质

了解正则表达式的默认特性。

导入

贪心性质

了解正则表达式的默认特性。

正则表达式的贪婪特性概述

正则表达式以其贪婪性著称。其贪婪特性旨在尽可能多地匹配字符,然后再将控制权交给表达式的下一部分。

我们来看一个例子。提供的文本是 'firstname' 'lastname' 'address'。

为了更好地理解,考虑零基索引。在上述文本中,单引号出现在 index[0],小写字母 "f" 出现在 index[1],小写字母 "s" 出现在 index[30],单引号出现在 index[31],依此类推。同样地,在正则表达式中,单引号出现在 index[0],通配符出现在 index[1],等等。

...
文本索引

正则表达式贪婪特性的运作方式

考虑正则表达式 /'.*' '.*'/。我们不直接关注模式匹配,而是逐步分析贪婪行为下的匹配过程。在了解所有特殊字符后,不妨先思考一下结果会是什么。

当搜索开始时,正则表达式中 index[0] 的字符(')与文本中 index[0] 的字符(')匹配。一旦该字符匹配成功,接下来的部分是 .*。通配符后跟重复量词,将开始执行。它会从文本的 index[1] 开始匹配,一直持续到文本末尾的 index[31]。通配符 . 可以匹配任意字符,而紧随其后的重复量词意味着它将持续匹配,直到文本结束。

正则表达式仍有部分需要匹配。因此,前面的 .* 会逐个释放已匹配的字符。每次释放后,正则表达式引擎会检查剩余部分是否能匹配。只要尚未找到成功匹配,前一段就会继续逐个释放字符。在这种情况下,.* 先匹配到文本末尾,然后开始回溯。正则表达式中 index[3] 的字符(')与文本中 index[31] 的字符(')匹配。

在 index[3] 的字符匹配成功后,正则表达式仍包含多个待匹配字符,全部都需要匹配才能完成整体成功匹配。但此时整个文本已被前面的部分完全匹配,因此前一部分必须释放字符。一旦字符被释放,匹配过程将重新开始。最终结果要么是成功匹配,要么是无匹配。

1var str = `'firstname' 'lastname' 'address'` 2console.log(str.match(/'.*' '.*'/));

正则表达式是贪婪的,它会尽快返回结果。正则表达式引擎会返回第一个成功的匹配,而“贪婪”意味着在将控制权交给下一部分之前,当前部分会尽可能多地匹配字符。这就是所谓的贪婪特性。

如你所见,表达式的第二部分在将控制权交给下一部分之前,匹配了所有可能的字符,导致后续无法匹配,从而触发回溯。

让我们继续处理文本的剩余部分。在 index[3] 的字符匹配成功后,正则表达式引擎移动到下一个字符。正则表达式中 index[4] 的字符是空格,需要进行匹配。但此时整个文本已被前面的部分完全匹配,因此前面的部分将开始逐个释放字符。首先是第三部分释放其字符——即引号。正则表达式中 index[3] 的字符(')无法与文本中 index[30] 的字符(s)匹配。

正则表达式引擎首先尝试将正则表达式中 index[3] 的字符(')与文本中的任意字符匹配。第二部分将继续释放字符,直到找到匹配为止。最终,正则表达式中 index[3] 的字符(')与文本中 index[23] 处的字符(')匹配成功。正则表达式继续到 index[4] 的空格字符,但它无法与文本中 index[24] 处的字符(a)匹配,于是再次发生回溯。最终,正则表达式中 index[3] 的字符(')与文本中 index[21] 处的字符(')匹配成功。随后,空格字符也成功匹配。

使用相同的模式,类似的过程也会发生。正则表达式中 index[5] 的字符(')将与文本中 index[23] 处的字符(')匹配。贪婪部分将在将控制权交给下一部分之前,从文本的 index[24] 匹配到 index[31]。由于字面字符无法匹配,再次触发回溯,最终整个正则表达式在文本中找到了完整匹配。

最终结果如下图所示。

...
最终结果

在下方代码工具中动手尝试,以更深入理解匹配过程。

1var str = `'firstname' 'lastname' 'address'` 2console.log(str.match(/'.*' '.*'/)); 3 4// console.log(str.match(/'.*' /)); 5// console.log(str.match(/ '.*'/)); 6// 取消注释这些行,查看输出以获得更清晰的理解。

为了避免正则表达式的贪婪行为,我们可以使用一个特殊字符。通过在需要惰性执行的部分后面添加 ? 来激活或表示这种惰性模式。虽然 ? 是重复量词,但在不同上下文中使用时,其含义变为“非贪婪”或“最小匹配”。

锚点字符

懒惰的本质