Perl正则表达式超详细教程(8)

\1表示引用第一个分组,\11表示引用第11个分组,在基础正则中,是不支持引用超出9个分组的,但显然perl会将\11的第二个1解析为引用,以便能引用更多分组。

同理\g1和\g11,只是使用\g引用的方式可以加上大括号使引用变得更安全,更易读,且\g可以使用负数来表示从右向左相对引用。这样在\g{-2}的左边添加新的分组括号时,无须修改引用表达式。

此处暂时还没介绍到命名分组,所以\g{name}和\k<name>留在后面再介绍。

\K表示强制中断前面已完成的匹配。例如"abc22ABC" =~ /abc\K2.*/;,虽然abc三个字母也被匹配,如果没有\K,这3个字母将放进$&中,但是\K使得匹配完abc后立即切断前面的匹配,也就是从c字母后面开始重新匹配,所以这里匹配的结果是22ABC。

再例如,"abc123abcfoo"=~ /(abc)123\K\g1foo/;,它匹配到123后被切断,但是分组引用还可以继续引用,所以匹配的结果是"abcfoo"。

贪婪匹配、非贪婪匹配、占有优先匹配

在基础正则中,那些能匹配多次的量词都会匹配最长内容。这种尽量多匹配的行为称为"贪婪匹配"(greedy match)。

例如字符串"aa1122ccbb",用正则表达式a.*c去匹配这个字符串,其中的.*将直接从第二个字母a开始匹配到最结尾的b,因为从第二个字母a开始到最后一个字母b都符合.*的匹配模式。再然后,去匹配字母c,但因为已经把所有字母匹配完了,只能回退一个字母一个字母地释放,每释放一个就匹配一次字母c,发现回退释放到倒数第三个字母就能满足匹配要求,于是这里的.*最终匹配的内容是"a1122c"。

上面涉及到回溯的概念,也就是将那些已经被量词匹配的内容回退释放。

上面描述的是贪婪匹配行为,还有非贪婪匹配、占有优先匹配,以下简单描述下他们的意义:

非贪婪匹配:(lazy match,reluctant)尽可能少地匹配,也叫做懒惰匹配

占有优先匹配:(possessive)占有优先和固化分组是相同的,只要占有了就不再交换,不允许进行回溯。相关内容见后文"固化分组"

有必要搞清楚这几种匹配模式在匹配机制上的区别:

贪婪匹配:对于那些量词,将一次性从左到右匹配到最大长度,然后再往回回溯释放

非贪婪匹配:对于那些量词,将从左向右逐字符匹配最短长度,然后直接结束这次的量词匹配行为

占有优先匹配:按照贪婪模式匹配,匹配后内容就锁住,不进行回溯(后文固化分组有具体示例)

除了上面描述的*量词会进行贪婪匹配,其他所有能进行多次匹配的量词可以选择贪婪匹配模式、非贪婪匹配模式和占有优先匹配模式,只需选择对应的量词元字符即可。如下:

(量词后加上?) (量词后加上+) 贪婪匹配量词 非贪婪匹配量词 占有优先匹配量词 ----------------------------------------------------------------- * *? *+ ? ?? ?+ + +? ++ {M,} {M,}? {M,}+ {M,N} {M,N}? {M,N}+ {N} {N}? {N}+

几点需要说明:

非贪婪匹配时的{M,}?和{M,N}?,它们是等价的,因为最多只匹配M次

在perl中不支持{,N}的模式,所以也没有对应的非贪婪和占有优先匹配模式

关于{N}这个量词,由于是精确匹配N次,所以贪婪与否对最终结果无关紧要,但是却影响匹配时的行为:贪婪匹配最长,需要回溯,非贪婪匹配最短,不回溯,占有优先匹配最长不回溯。

看以下示例即可理解贪婪和非贪婪匹配的行为:

$str="abc123abc1234"; # greedy match if( $str =~ /(a\w*3)/){ print "$&\n"; # abc123abc123 } # lazy match if( $str =~ /(a\w*?3)/){ print "$&\n"; # abc123 }

以下是占有优先匹配模式的示例:

$str="abc123abc1234"; if( $str =~ /a\w*+/){ # 成功 print "possessive1: $&\n"; } if( $str =~ /a\w*+3/){ # 失败 print "possesive2: $&\n"; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e1a716f6fc1f35a6ad219d4af05ea1f5.html