贪婪模式
默认情况下,所有的限定词都是贪婪模式,表示尽可能多的去捕获字符,能匹配多少就匹配多少。从正则语法的角度来讲,被匹配优先量词修饰的子表达式使用的就是贪婪模式,如/a+/
。
标识符:+,?,*,{n},{n,},{n,m}
非贪婪模式
在限定词后增加?
,则是非贪婪模式,表示尽可能少的去捕获字符。
从正则语法的角度来讲,被忽略优先量词修饰的子表达式使用的就是非贪婪模式,如/a+?/
。标识符:+?,??,*?,{n}?,{n,}?,{n,m}?
1 | const str = "aaab", |
回溯
正则表达式中有个优先规则:最先开始的匹配拥有最高的优先权
1 | /*表达式1*/ |
💡该贪婪匹配表达式在引擎中的回溯表现如下:
- 第一个a取得控制权,匹配正则中的a,匹配成功,控制权交给
a*
; a*
取得控制权后,由于这是贪婪模式下的标识符,因此在可匹配可不匹配的情况下会优先匹配,因此尝试匹配1处的字符a;- 依次成功匹配
a、a、a、a、a、a
,接下来依旧保持贪婪特性匹配字符串中b,匹配失败,向前查找可供回溯的状态,将控制权交给a*b
; a*b
取得控制权后,开始匹配末尾处的b,匹配成功;- 至此,整个正则表达式匹配完毕,匹配结果为
aaaaaaab
,匹配过程中回溯了1次。
💡该非贪婪匹配表达式在引擎中的回溯表现如下:
- 第一个a取得控制权,匹配正则中的a,匹配成功,控制权交给
a*?
; a*?
取得控制权后,由于这是非贪婪模式下的标识符,因此在可匹配可不匹配的情况下会优先不匹配,因此尝试不匹配任何内容,将控制权交给b;- b取得控制权后,开始匹配1处的a,匹配失败,向前查找可供回溯的状态,控制权交给
a*?
,a*?吃进一个字符,index到了2处,再把控制权交给b; - b取得控制权后,开始匹配2处的b,匹配失败,重复上述的回溯过程,直到
a*?
匹配了6处的a字符,再将控制权交给b; - b取得控制权后,开始匹配7处的b,匹配成功;
- 至此,整个正则表达式匹配完毕,匹配结果为
aaaaaaab
,匹配过程中回溯了6次。
多分支表达式匹配
1 | 'It will be confirmed in a subsequent console message'.match(/message|in|console/); |
💡在本例中,匹配过程如下:
- 正则多选分支
/message|in|console/
从左边开始匹配,第一个message取得控制权,匹配字符串中的I,匹配失败,返回检查点进行回溯,控制权交给in; - in取得控制权后,匹配字符串中的I,匹配成功,在1处匹配失败,进行回溯,控制权交给 console;
- 同上,console匹配失败,则在待匹配字符串中后移一位,即1处字符n重新进行第一步匹配;
- 同上,所有分支均匹配失败;
- 由待匹配字符串和上述匹配规则可知,in将在字符串n处最早匹配成功,至此,整个正则表达式匹配完毕,匹配结果为
in
。