正则表达式的回溯

正则表达式的回溯

总的来说,就是使用正则表达式时,因为其性能是不稳定的,当使用不恰当时,容易引发性能问题。
因为正则表达式会有回溯问题,当匹配的是一串很长的字符串时,如果发生回溯,其计算量就将会是非常的巨大,这就是性能差的主要原因。
什么是回溯呢,就比如匹配字符串“abbc”,正则表达式为/ab{1,3}c/,因为默认是贪婪模式,
所以会尽量匹配多一点内容,也就是想尽量匹配多个b,于是步骤就是如下:
1. a    ->   a
2. ab   ->   ab
3. abb  ->   abb
4. abbb ->   abbc
5. abb  ->   abb
6. abbc ->   abbc
如上,第4步因为想要尽可能的匹配多一点内容,所以想要匹配3个b,但是没匹配上,匹配到了c,
于是就回溯,然后匹配下一个正则表达式,也就是c,然后c与c匹配,成功返回。
这就是正则表达式的回溯问题,当需要匹配的是一个超长字符串,并且发生了回溯问题,那其计算量能够想象有多大了吧。

解决回溯问题:
由于是因为贪婪模式导致的,那只要把贪婪模式改为懒惰模式即可,只要后面加个“?”就行,改为/ab{1,3}?c/
但是懒惰模式也无法完全回溯问题,比如:字符串“abbc”,正则表达式/ab{1,3}?c/,则步骤如下:
1. a     ->   a
2. ab    ->   ab
3. abc   ->   abb
4. ab    ->   ab
5. abb   ->   abb
6. abbc  ->   abbc
如上,第3步因为想要尽可能少匹配一点内容,于是就只匹配一个b,但没匹配上,于是就回溯,
与贪婪模式相反,贪婪模式是字符串回溯,而懒惰模式是正则表达式回溯。
 
使用独占模式,只要后面加个“+”就行,改为/ab{1,3}+c/
因为独占模式是只要不匹配就结束,不会进行回溯,但是也不能完全解决回溯问题,因为其也是会尽可能的匹配多一点内容,所以也会导致回溯问题。

总的来说,懒惰模式和独占模式都是只能减少回溯问题,但是不能完全避免回溯问题。

可优化方案:
1. 少用贪婪模式,多用独占模式;
2. 减少分支选择,比如(X|Y|Z)这种分支选择,如要只用分支,可以将常用的选项放在前面,可以提取公共因子,比如(aabb|aacc|aadd)可以换成aa(bb|cc|dd),可以用三次匹配来代替(X|Y|Z)3. 减少捕获嵌套,就是一个()代表一个捕获组,比如/a(bc)de(fgh)ijk(lmn)/,然后\1代表(bc),\2代表(fgh),\3代表(lmn),
非捕获组就是(?:X),比如/a(?:bc)de(fgh)ijk(?:lmn)/,则\1代表(fgh),或者直接不用括号/abcde(fgh)ijklmn/4. 能不用正则表达式就不用正则表达式。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值