[Regular] 4、正则表达式的匹配原理原则

原则一:优先选择最左端(最靠开头)的匹配结果
  根据这条规则,起始位置最靠左端的匹配结果总是优先于其他可能的匹配结果。这里没有规定优先匹配结果的长度,而只是规定,在所有可能的匹配结果中,优先选择开始位置靠左端的。
  匹配过程:正则匹配先从需要查找的字符串的起始位置开始,尝试匹配整个表达式能匹配的所有样式文本,如果在当前位置测试了所有可能之后不能找到匹配结果,正则引擎就是启动传动装置向右移动一个位置,也就是从字符串的第二个字符之前的位置开始重新尝试。在找到匹配结果以前必须在所有位置重复此过程。只能在尝试了所有位置(从第一个字符直到最后一个字符)都不能匹配结果的情况下,才会报告“匹配失败”。
所以如果用ee来匹配abeen的话,从字符串开始第一轮尝试失败(因为ee不能匹配ab),第二轮尝试也失败(因为ee也不能匹配be),直到第三软尝试能够成功,引擎会停止下来报告匹配ee成功.
  如果不了解这个规则,有时候就不能理解匹配的结果。如用abeen来匹配:“this is 123abeen321 test by abeen”. 结果会是123abeen321中的abeen被匹配,而不是最后的abeen。

原则二:标准的匹配量词*、+、?、{min, max}是匹配优先的
    标准量词是匹配的,在匹配成功之前,进行尝试的次数是存在上限和下限的,匹配优先量词之所以得名,是因为他们总是(或者至少是尝试)匹配多于匹配成功下限的字符。也就是说,标准匹配量词的结果可能并非所有可能结果中最长的,但它们总是尝试匹配可能多的字符,直到匹配上限为止。
    例如: [0-9]+为什么能匹配ABeen 19820527 中的所有数字。1匹配成功之后,实际上已经满足了成功的下限,但此表达式是匹配优先的,所以它不会停止在此处,而会继续下去。继续匹配19820527,直到字符串结束。
过度的匹配优先
  ^.*(?<Test>[0-9][0-9])能够匹配一行字符串的最后两位数字,如果有的话将它们存于Test 组中。来看一下匹配过程, .* 首先匹配整行,而[0-9][0-9]是必须匹配的,在尝试匹配行末的时候会失败,它样它会通知.*自己没法匹配了,为了大局着想,大哥你还是交出点来吧。于是.*很有大哥风范,以大局为重交出一个字符,如果不够还会继续交出字符。当然前提是大哥得先留下自己那份,也就是匹配成功的下限。
    我们来看 ^.*(?<Test>[0-9][0-9]) 匹配 this is a test abeen 1982abeen的过程。.*首先匹配整个字符串以后,第一个[0-9]的匹配要求.*释放一个字符n,但是[0-9]还不能匹配,所以.*必须继续交还字符e,如此循环只到交还2为止。但不幸的是第一个[0-9]匹配成功后,第二个[0-9]不能匹配成功,于是.*大哥再次以大局为重,又释放一个字符8,这样整个表达式就匹配成功,结果是this is a test abeen 1982,Test内容为82.
先来先服务
    如果想用^.*(?<Test>[0-9]+)来匹配一行的最后整个数字,比如匹配this is a test abeen 1982,结果Test只捕获了2,这是为什么呢? 
    你的本意也许是想捕获1982,但结果为什么是2呢!首先.*会捕获整个字符串,然后[0-9]+必须要捕获( 注意是必须)一个数字,所以.*交还了一个2出来,接下来整个表达式中没有必须要匹配的元素了,所以.*不会再交还字符。结果Test只能捕获2了。
  这就是“先来先服务”原则,匹配优先的结构只会在被迫的情况下交还字符。

posted @ 2009-06-04 01:01  ABeen  阅读(875)  评论(0编辑  收藏  举报