条款40 预编译正则表达式
马上回答--下面的Perl正则表达式包含哪些部分?/abc/
答案是两部分:一个是匹配操作符,一个是内部的正则模式。匹配操作符的目的是要将正则模式同匹配目标联系起来,但匹配操作符和其内部的正则模式并不一定要同时出现。
我们可以抛开匹配或替换操作符,直接用qr//定义模式,然后使用这个已经编译过的正则表达式。它在语法上和定义字串没什么区别:my $name='Buster';
my $regex=qr/\b$name\b/;
除了匹配操作符中内插的字串以外,其他出现在正则表达式中的元字符具有特殊含义。变量$regex的值变成了刚刚编译过的这个正则表达式的虚拟引用。实际上它只不过是带一点点魔法特性的普通字串而已,用ref函数来看就像是引用 ,但如果真的对它解引用的话,得到的却是undef。不管怎样,打印这个变量,就会看到下面这条正则表达式结构,一如之前我们定义的那样:(?-xism:\bBuster\b)
定义摸式的时候同样可以加上各种修饰,比如/i、/m或是/s。在下面这个例子中,不区分大小写,点号可以匹配换行符,因此两个名字之间可以跨行:my $regex=qr/Buster(.*)Mimi/si;
我们可以把编译好的$regex用在匹配或替换操作中,就好比直接使用普通文本一样:# 计算@big_long_list中magic_word的出现次数
foreach (@big_long_list) {
$count += /$regex/; # 之前就已编译过
}
甚至略掉匹配操作符也行,虽然看上去有点怪怪的 :$string=~ $regex;
我们还可以在使用某条正则表达式之前,先用qr//测试一下,看能否通过编译,而不必等到应用时才发现模式本身有问题。可借助eval检测正则表达式编译结果:my $name='(';
my $regex=eval{ qr/\b$name\b/ }
or die "Regex failed: $@";
如果$name中的左括号(没有配对,内插后得到的模式就不完整,因此eval抛出错误提示。而Perl会很尽责地向你汇报困惑之处:Unmatched ( in regex; marked by
要点
用qr//操作符预编译正则表达式。
将预编译过的正则表达式内插到匹配操作符中使用。
用eval检测模式非法的正则表达式。
【责任编辑:云霞 TEL:(010)68476606】
点赞 0