再看一个忽略优先的情况,使用`a.*?d`去匹配字符串“caaadc”,我们发现当匹配成功a时,引擎有两条路,会选择忽略匹配,直接匹配d,但是字符串“caaadc”的a后面是a,所以失败,回溯到之前的选择,悬着匹配,获得“aa”,然后又一次遇到同样的问题,引擎选择忽略匹配,发现后面又是a,不能匹配d,再次回溯,选择匹配,得到“aaa”,这一次忽略匹配后发现后匹配成功了d,那么上报成功,得到“aaad”。
希望这几个例子能够大概讲解清楚这两种不同的情况吧!
2.2回溯 环视
环视结构不匹配任何字符,只匹配文本中的特定位置,这一点和单词分界符`\b`、`^`、`$`相似。
`(?=)`称作肯定顺序环视,如`x(?=y)`是指匹配x,仅当后面紧跟y时,如果符合匹配,则只有x会被记住,y不会被记住。
`(?!)`称作否定顺序环视,如`x(?!y)`是指匹配x,仅当后面不紧跟y时,如果符合匹配,则只有x会被记住,y不会被记住。
在环视内部的备用状态一旦退出环视范围后立即清除,外部回溯不能回溯到环视内部的备用状态。使用`ab\w+c`和`ab(?=\w+)c`来匹配字符串“abbbbc”,第一个表达式会成功,而第二个表达式会失败。
例子1:
var reg=/ab(?=c)/;
var result1=reg.exec("abcd");
var result2=reg.exec("abbc");
document.write(result1+" "+result2);
结果:
例子2:
var reg=/ab(?!c)/;
var result1=reg.exec("abdc");
var result2=reg.exec("abcd");
document.write(result1+" "+result2);
结果:
例子3:
var reg1=/ab\w+bc/;
var reg2=/ab(?=\w+)c/;
var result1=reg1.exec("abbbbbcb");
var result2=reg2.exec("abbbbbbc");
document.write(result1+" "+result2);
结果:
明显自己都觉得环视没讲解好,还有肯定逆序环视和否定逆序环视,以及固化分组这些都是在解决回溯的问题,回溯算是影响表达式的罪魁祸首吧!这几个内容看啥时候有时间在细讲吧!写着写着才发现想让人看懂不是那么容易的!体谅一下哦!
3、打造高效正则表达式
Perl、Java、.NET、Python和PHP,以及我们熟悉的JS使用的都是表达式主导的NFA引擎,细微的改变就可能对匹配的结果产生重大的影响。DFA中不存在的问题对NFA来说却很重要。因为NFA引擎允许用户进行精确控制,所以我们可以用心打造正则表达式。
3.1先迈好使的腿
对于一般的文本来说,字母和数字比较多,而一些特殊字符很少,一个简单的改动就是调换两个多选分支的顺序,也许会达到不错的效果。如使用`(:|\w)*`和`(\w|:)*`来匹配字符串“ab13_b:bbbb:c34d”,一般说来冒号在文本中出现的次数少于字母数字,此例中第一个表达式效率低于第二个。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-22527-3.html
可能有人还以为我也是做广告的