贪婪匹配(Greedy)

正则中,表示量词的都是默认贪婪,在贪婪模式下,会尽可能的去匹配最大长度的字符。

例子: 使用正则 a* 匹配 aaabb

  • 字符串:a a a b b
  • 下标:0 1 2 3 4 5
匹配 开始 结束 说明 匹配内容
第 1 次 0 3 匹配 aaa 三个字符,遇到 b 停下 aaa
第 2 次 3 3 匹配剩下的 bb, 匹配不成功,输出空字符串 ‘’
第 3 次 4 4 匹配设下的 b,匹配不成功,输出空字符串 ‘’
第 4 次 5 5 匹配空字符串 ‘’

image.png
所以说,贪婪模式会最大长度的匹配字符串,如果哟啊最短长度的匹配,则使用非贪婪匹配模式。

非贪婪匹配(Lazy)

如果要使用非贪婪模式,则需要在两次后面加入英文字符 (?) ,贪婪匹配就变成了非贪婪匹配了。
image.png

这次的匹配结果都是单个 a 包括 a 左右两边的空字符串都匹配上了。

回溯

贪婪模式和非贪婪模式都会有回溯的问题,那么什么是回溯呢?

先看贪婪模式下的例子

  1. var reg = /a*ab/
  2. var str = 'aaaaab'

步骤:

  1. a* 匹配时,会尽可能多的匹配字符 a ,匹配结果为 aaaaa ,剩余字符 b
  2. ab 匹配时,此时只剩一个字符 b ,匹配不成公布,之前匹配的 aaaaa 就会向后吐出一个字符 a 出来,剩余字符 ab
  3. 最后 ab 匹配剩余字符成功

上述在 a* 匹配后,剩余匹配正则需要 a* 匹配的结果吐出一个字符 a 出来,这就是向后回溯

再看一些非贪婪模式的例子

  1. var reg = /y{1,3}?z/
  2. var str = 'yyz'

步骤:

  1. y{1,3}? 会及可能少的匹配字符 y,匹配上一个 y 之后,剩余字符 yz
  2. 此时 z 回去匹配剩余字符中的 y ,但是匹配不上, y{1,3}? 向前再匹配一个字符 y ,剩余 z
  3. 最后 z 匹配剩余字符成功

上述向前再匹配的一个行为就是向前回溯。

独占模式

独占模式跟贪婪模式很像,独占模式会尽可能多的匹配,如果匹配失败就结束。
独占模式是在量词后面加个加号 (+)
注意:JavaScript 不支持独占模式

以下例子的编程语言为 PHP
image.png
image.png

三种比较

模式 正则 文本 结果
贪婪模式 a{1,4}ab aaaab 成功
非贪婪模式 a{1,4}?ab aaaab 成功
独占模式 a{1,4}+ab aaaab 失败

贪婪模式、非贪婪模式与独占模式 - 图5