VBA正则表达式入门与提高(7)

2019-07-13 17:32

正则表达式入门与提高

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)

29

VBA平台的正则学习参考资料

表示匹配后面跟着字符串”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”.

最后要指出一点的是:虽然环视表达式中有圆括号,但它是非捕获性的.并且圆括号与?、!或=是一个不可分割的整体.

30

正则表达式入门与提高

(二)捕获性括号(?)与非捕获性括号(?:?).

1.捕获型括号(?.)

前面已经多次遇见过捕获性括号”(?)”, 总结前面使用圆括号有二个理由: 1) 分组,标明量词的作用范围.或限制多选结构,标明选择符”|”的作用范围. 例:一文本中,有多行文本,提取行全部以”AA”开头的连续3行. 正则表达式: (^AA.*\\n){3}

^AA 锁定行特征,即行开始处有字符AA;

.* 匹配行中其它字符至换行符,英文句点”.”是不能匹配换行符的; \\n 匹配换行符;

^AA.*\\n 匹配一个完整行;

(^AA.*\\n){3} 用()分组标明后面量词{3}的作用范围,即行重复3次. 2) 捕获文本,将括号内容的内容保存在特殊变量中. 在VBA中,捕获性括号保存的内容有三种方式引用: (1) 在Replace方法中通过$1,$2?方式引用; (2) 在正则表达式中,通过\\1,\\2?方式引用.

(3) 可以用匹配对象的Submatches集合索引号提取其内容. 3) 关于重复分组

如果在分组的结束之后放一个量词,那么整个分组就会被重复.如(abc){3}与abcabcabc是相同的. 那么最后捕获性括号捕获的内容是什么呢? 例:正则表达式 (\\d\\d){1,3} 目标文本:123456

最后匹配结果是123456.$1的值,即捕获性括号捕获到的内容是56.你可以编制代码测试,用submatches属性提取该值验证.得到这个结果的原因是:

分组的匹配在每次引擎退出该分组的时候被捕获,并会覆盖该分组在之前匹配的任何文本.(\\d\\d){1,3}会匹配一个包含2个,4个或6个数字的字符串.引擎会退出该分组3次.当这个正则表达式匹配到123456的时候,捕获分组中保存的是56,因为该分组的最后一次循环存储的是56.另外两次匹配12和34被覆盖了.

2.非捕获型括号(?:?)

捕获性括号保存内容时,是会付出处理成本的.所以,如果只需要让它起分组作用,而不必保存之中内容.

31

VBA平台的正则学习参考资料

正则表达式提供了一个非捕获性括号的字符序列:(?:?.),在形式上比捕获性括号多一个”?:”,并紧跟在左括号之后,它们是一个整体.

例:

(?:中国|China) (?:.*)

使用非捕获性括号可提高一定的匹配效率,特别是在使用循环的时候. 再次指出的是,虽然环视中也有圆括号,但在那里是非捕获性的.

(三)抑制量词的贪婪性: ?

前面已经知道,所有量词都是贪婪的,或称之为匹配优先的.他们总是匹配尽可能多的字符.下面例子可以了解什么是贪婪:

目标文本:“This is a first test” 要求:匹配提取标签 正则表达式: <.*> 代码: Sub test() Dim mh, s$

s = \ WithCreateObject(\ .Pattern = \ .Global = True Set mh = .Execute(s) End With MsgBox mh(0) End Sub 讨论:

在正则表达式中,使用了量词\它表示可匹配0个或多个字符.执行该代码结果显示:first.为什么不是我们希望的结果呢?下面分析它的匹配过程:

32

正则表达式入门与提高

当用正则表达式\作用于目标文本时,首先用\去目标文本中尝试,结果在\标签\后面找到了\紧接着开始在下一个位置尝试”.*”,\可匹配任意非换行符,\可以表示可以连续0次或多次.由于量词\匹配是匹配优先的,当匹配模式”.*”时,它会匹配至行的末尾,直到遇到换行符为止.下来该尝试表达式中的\了,结果余下的字符是换行符,不能匹配字符”>”,在此匹配失败;

在原理中我们会讲到,这时引擎会回退,直至回退到右边第一次出现”>”字符,匹配成功.最后报告成功匹配结果:first

为了解决这类问题,正则引入了一个元字符”?”,将它紧跟在量词之后,如”.*?”,则可抑制量词的贪婪性.让它变成忽略优先量词.忽略优先量词总是匹配尽可少的字符

同上例,正则表达式修改为: <.*?>

其它代码不变,最后结果显示:,得到了我们希望的结果.(提示:从效率上看,本例用正则表达式”<[^>]*>”效率更高.其原因会在”原理篇”中会谈到)

上面的例子告诉我们,在匹配优先的量词后,紧跟一个”?”,则变成了”忽略优先量词”.它们总是匹配尽可少的字符.再举一例,在字符串“oooo”中,“o+?”只匹配单个“o”,而“o+”匹配所有“o”

如果你已经读到了这里,那么恭喜你.你应该有很厚的正则功底了.

尽管现在的你可以用正则来处理一些文本工作,但难免给人以”花架子”的印象.因为也许你用正则完成的任务,远不如用VBA自身函数或方法处理来得简洁快速.正则是用来处理,VBA难以为任的工作.所以,你需要进一步深入下去.

33


VBA正则表达式入门与提高(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:叉车司机复习题

× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: