|
楼主 |
发表于 2014-6-11 15:57
|
显示全部楼层
本帖最后由 liu-aguang 于 2014-6-17 19:18 编辑
五.正则元字符—-字符(串)位置表示法
正则提供了一些表示位置元字符(序列),它可以锚定特定字符(串),有时使用它们可以提高匹配效率.除了前面介绍的^和$外,还有:
(一)单词分界符\b
在英文环境中,匹配一个字边界,即字与空格间的位置。例如,“er\b”匹配“never”中的“er”,但不匹配“verb”中的“er”。
它匹配这样一个位置:该位置一边是英文单词字符,另一边不是.也可以理解为该位置两边的字符,其中一个可以被\w匹配,另一个字符则可被\W匹配.所以在英文环境中,可匹配四种位置 (本文中英文单词字符指[a-zA-Z0-9_]):
1) 在字符串的第一个字符前的位置(如果字符串的第一个字符是一个“单词字符”)
2) 在字符串的最后一个字符后的位置(如果字符串的最后一个字符是一个“单词字符”)
3) 在一个“单词字符”和“非单词字符”之间,其中“非单词字符”紧跟在“单词字符”之后
4) 在一个“非单词字符”和“单词字符”之间,其中“单词字符”紧跟在“非单词字符”后面
下面这个例子可让你明白单词分界符的用途:
目标文本:He captured a catfish for his cat
正则表达式1:
cat
正则表达式2:
\bcat\b
任务要求:用字符串fat,替换文本中的cat.
代码:
sub test()
dim s$
with createobject("vbscript.regexp")
.pattern="cat" '分别用上面两个表达式测试
.global=true
s=.replace("He captured a catfish for his cat","fat")
end with
msgbox s
end sub
你能分析结果差异的原因吗?
(二)非单词边界\B
非字边界匹配。“er\B”匹配“verb”中的“er”,但不匹配“never”中的“er”。
它是\b取反.\B总是匹配两个同时被\w或\W匹配的字符之间的位置.它匹配下列位置:
1)在目标文本的第一个字符之前如果第一个字符不是单词字符;
2)在目标文本的最后一个字符之后,如果最后一个字符不单词字符;
3)在两个单词字符之间;
4)在两个非单词符之间;
5)空串
在非英文环境中,没有单词边界;全部是非单词边界.所以应用范围很窄.
(三)肯定顺序环视与否定顺序环视
以一个实例来讨论:
1) (?=98)
2) (?!98)
第一个是肯定环视,表示子字符串”98”前面的位置;第二个是否定环视,表示不是子字符串”98”的位置.
例:
目标文本:”window97升级为window98”
如果把它们作为正则表达式作用于该文本,则该文本中只有”98”前一个位置上才能被(?=98)匹配;除这个位置外,其它所有位置都可以被(?!98)匹配.它的工作原理是:
在每个位置上查找该位置后是否跟着一个字符9,再然后再跟着一个字符8.如果是,则(?=98)报告匹配成功,(?!98)报告匹配失败;反之,(?=98)报告失败,(?!98)报告成功.
利用它们可以锚定特定字符串,如:正则表达式
Window(?=98)
表示匹配后面跟着字符串”98”的字符串”window”.如果用它作用于上面目标文本,那么它只能匹配window98前面的”window”.
而正则表达式:
Window(?!=98)
表示匹配后面没有跟着字符串”98”的字符串”window”.如果用它作用上面目标文本,那么它它只能匹配widow97前面的”window”
环视只是简单地测试其中子表达式能否在当前位置匹配后面的文本.无论是什么样的结果,它都不会”占有”被测试的文本.例:
目标文本:”正则ABC”
正则:(?!=\W+).{2}
代码:
Sub test()
Dim re,mh,s$
S=”正则ABC”
With createobject(“vbscript.regexp”)
.pattern=”(?=\W+).{2}”
Set mh=.Execute(s)
End with
For each k in mh
Debug.print k ' “正则”
next
End sub
讨论:
匹配结果是:”正则”.我们来分析一下匹配过程:
在文本的开始位置,正则引擎首先尝试(?!=\W+),即检查该位置后面有无一个或一个以上的非英文单词字符.结果它找到"正则"二个字符是非英文字符,引擎报告第一个子表达式匹配成功;接着尝试第二个子表达式:”.{2}”,即匹配两个任意字符,这两个字符就是”正则”.正则表达式中子表达式尝试完毕,最后报告成功而结束.
我们看到(?!=\W+),并没有”消耗”掉”正则”字符串,如果消耗了,那么结果应该是”AB”.
最后要指出一点的是:虽然环视表达式中有圆括号,但它是非捕获性的.并且圆括号与?、!或=是一个不可分割的整体.
补充内容 (2016-10-29 20:34):
更正: 正则中没有(?!=...), 本页中出现的(?!=...)是笔误, 应该为(?!...) |
|