贪婪匹配(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 | 匹配空字符串 | ‘’ |
所以说,贪婪模式会最大长度的匹配字符串,如果哟啊最短长度的匹配,则使用非贪婪匹配模式。
非贪婪匹配(Lazy)
如果要使用非贪婪模式,则需要在两次后面加入英文字符 (?) ,贪婪匹配就变成了非贪婪匹配了。
这次的匹配结果都是单个 a 包括 a 左右两边的空字符串都匹配上了。
回溯
贪婪模式和非贪婪模式都会有回溯的问题,那么什么是回溯呢?
先看贪婪模式下的例子
var reg = /a*ab/
var str = 'aaaaab'
步骤:
a*
匹配时,会尽可能多的匹配字符a
,匹配结果为aaaaa
,剩余字符b
ab
匹配时,此时只剩一个字符b
,匹配不成公布,之前匹配的aaaaa
就会向后吐出一个字符a
出来,剩余字符ab
- 最后
ab
匹配剩余字符成功
上述在 a*
匹配后,剩余匹配正则需要 a*
匹配的结果吐出一个字符 a
出来,这就是向后回溯。
再看一些非贪婪模式的例子
var reg = /y{1,3}?z/
var str = 'yyz'
步骤:
y{1,3}?
会及可能少的匹配字符 y,匹配上一个y
之后,剩余字符yz
- 此时
z
回去匹配剩余字符中的y
,但是匹配不上,y{1,3}?
向前再匹配一个字符y
,剩余z
- 最后
z
匹配剩余字符成功
上述向前再匹配的一个行为就是向前回溯。
独占模式
独占模式跟贪婪模式很像,独占模式会尽可能多的匹配,如果匹配失败就结束。
独占模式是在量词后面加个加号 (+)
注意:JavaScript 不支持独占模式
以下例子的编程语言为 PHP
三种比较
模式 | 正则 | 文本 | 结果 |
---|---|---|---|
贪婪模式 | a{1,4}ab | aaaab | 成功 |
非贪婪模式 | a{1,4}?ab | aaaab | 成功 |
独占模式 | a{1,4}+ab | aaaab | 失败 |