|
楼主 |
发表于 2015-9-11 01:47
|
显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件 ★ 免费下载 ★ ★ 使用帮助★
本帖最后由 小花鹿 于 2015-9-11 10:48 编辑
失败原因:
目标文本: 在1998年又出版了windows98 ,和97一样,98也OK也很好用
正则: (?=windows)(?=\d+年).*OK(.*)
此正则可看成三个子表达式:(1) (?=windows) ; (2) (?=\d+年); (3) .*OK(.*)
匹配过程:
从左至右, 在"在1998年又出版了"每个字符上测试正则的子表达式(1)都是失败的, 直到字符"w"所在位置处子表达式(1)匹配成功,这时在同一位置处测试子表达式(2),显然失败. 于是引擎继续在目标文本中移动到下一位置, 即"i"所在位置, 而引擎通过"回溯"机制,正则表达式重新回到子表达式(1)处,用子表达式(1)去"i"所在位置尝试匹配,肯定会失败.直至行尾的每个位置上子表达(1)都是失败的. 最后引擎报告结果---整体匹配失败.结束!
按题意,可以用一个更容易理解正则完成任务:
^.*?(?:windows|\d+年).*?(?:windows|\d+年).*?OK(.*)
.....................................................................................................分割线................................................................
第一个问题:
这种解释我看明白了,现在我用自己的话再复述一遍:
从左至右,先在“在”这个字符位置上开始,测试子表达式1,不跟windows ,所以失败,再移动到下一位置“1 “,同样也不跟windows ,所以也匹配失败,一直到“了”都是失败的,直到“w” 开始紧跟windows ,所以子表达式1匹配成功,当子表达式1匹配成功后,位置不向下移动,而是在“w” 这个位置开始尝试匹配子表达式2,也就是说从“w” 这个位置开始是不是紧跟子表达式2 ,显然不成功,然后移动到下一位置“i” ,这时再尝试子表达式1,肯定失败,由此向右,子表达式1一直是失败的,所以,最后结果是失败。
但是,如果把子表达式1改成 (?=.*?windows) ,情况就不同了:
从左至右,先在“在”这个位置上用“在”匹配.*?,成功,再匹配windows ,不成功,回溯,再用“1” 匹配.*? ,成功,再匹配windows ,不成功,再回溯,一直到“了”与.*? 匹配成功,再匹配windows ,成功,这时位置还在“在”上面,这时从“在”这个位置开始,尝试子表达式2(\d+年),先用“在”匹配子表达式2,不成功,再用“1” 匹配子表达式2,也不成功,一直到8前面的9,都不成功,但是到了“8” ,与子表达式匹配成功,这时位置仍然在“在”上面,在子表达式1 和子表达式2 成功的基础上,从“在”开始再尝试匹配子表达式3,显然是成功的,所以最终的结果是匹配成功。
其实(\d+年) 应该改成 (\d+?年)
....................................................................
上面这段表达有误,子表达式2匹配成功后,位置不应该在“在”上,而应该在“1” 上。
(\d+?年) 应该是 (\d+年)
....................................................................
第二个问题:
你所写的这个表达式 ^.*?(?:windows|\d+年).*?(?:windows|\d+年).*?OK(.*) 很好,很容易理解。
其实我事先也有个答案:(?=.*windows)(?=.*\d+年).*OK(.*) 只是效率不高,现在想想应该改成:(?=.*?windows)(?=.*?\d+年).*?OK(.*)
|
|