六、环视的多角度理解与应用 环视按引擎往前(右)看还是往后(左)看,分为顺序环视和逆序环视.VBscript正则只支持往前看的顺序环视.环视有多种叫法,如”零长度断言”等. 对肯定顺序环视(?=exp)来说:从位置的角度理解,表示该位置是子表式exp左面紧挨的位置;从”断言”的角度理解,它断言自身出现的右边能匹配文本exp. 否定环视则是相反的情况. 从匹配过程来理解,顺序环视是从左至右查看文本,尝试匹配exp,如果能够匹配,那么肯定顺序环视(?=exp)报告成功,而否定顺序环视(?!exp)报告失败.反之,如果不能够匹配,那么肯定顺序环视报告失败,而否定顺序环视报告成功. 从环视的应用来说,主要有两个方面:
(一)用作锁定特定位置的文本字符串
例1:将文本中的”windows98,windows97,windowsxp”中的字符串”windows”替换为”win” 正则: Windows(?=98|97|xp) 这个正则表达式锁定了字串”windows”: 在目标文本中,只有字符串”98”或”97”或”xp”前面的”wordows”才会得到匹配.它排除了在其它位置上存在的”windows”字符串. 例2:查找后面不跟着某个特定单词(如Cat)的任意单词 正则: \b\w+\b(?!\W+cat\b) 这个正则表达式首先用”\b\w+\b”去匹配一个单词,如匹配成功,紧接着尝试表达式(?!\W+cat\b),它的意思是查找该位置之后有无这样的字符串:若干个非单词字符(如空格)后跟着单词”cat”. 如果没有,则环视部分报告匹配成功,于是整个正则表达式匹配尝试结束,最终成功匹配,匹配结果为第一部分找到的单词. 反之,如果有,则环视部分报告匹配失败,于是整个正则表达式匹配失败,最终结果是,第一部分找到的单词不是符合要求的. 要注意的是在环视的子表达式中,Cat后用了单词边界\b,是避免把某一个单词内部的cat字符当成单词了. 例3:查找不重复的单词 正则: \b(\w+)\b(?!.*?\b\1\b) 前面我们介绍过查找相邻重复单词的正则表达式: \b(\w+)\s+\1\b 你能否写一个查找相邻或不相邻的重复单词的正则表达式呢?
(二)用作对特定字符串是否存在的判断
例1:搜索同时包含多个单词的文本行,如:搜索包含单词one和two的文本行 正则: ^(?=.*?\bone\b)(?=.*?\bwo\b).+$ 例2:查找除某个单词(cat)之外的任意单词 \b(?!cat\b)\w+ 例3:查找不包含另一个单词(cat)的单词 \b((?!cat)\w)+\b 例4:匹配不包含某个单词(cat)的整行 ^((?!\bcat\b).)*$ 请自己仔细解读这几个可在实际工作应用的经典正则表达式. 小结:与锁定文本功能不同,用作判断时,环视结构是放在前面的,匹配尝试时,它将在指定位置判断是否存在特定的字符串(即尝试匹配环视结构内的子表达式),如果环视报告成功则继续下一字符的匹配尝试;如果环视报告失败,则宣布整个匹配过程失败. 例1中指定位置是从行开始位置尝试子表达式的匹配; 例2中是从每个单词边界尝试子表达式的匹配; 例3和例4是在单词内部或行内部的每个位置尝试匹配子表达式,所以效率较低.另外,如果不需要提取文本,例3和例4中的捕获括号可修改为非捕获性括号. |