ASP站长网正则表达式两篇:
 
基础正则
Perl正则
本文是对Perl正则的一点扩展,主要内容是使用qr//创建正则对象,以及一些其它的技巧。
 
qr//创建正则对象
 
因为可以在正则模式中使用变量替换,所以我们可以将正则中的一部分表达式事先保存在变量中。例如:
$str="hello worlds gaoxiaofang";
$pattern="w.*d";
$str =~ /$pattern/;
print "$&\n";
 
但是,这样缺陷很大,在保存正则表达式的变量中存放的特殊字符要防止有特殊意义。例如,当使用m//的方式做匹配分隔符时,不能在变量中保存/,除非转义。
 
perl提供了qr/pattern/的功能,它把pattern部分构建成一个正则表达式对象,然后就可以:
 
在正则表达式中直接引用这个对象
可以将这个对象保存到变量中,通过引用变量的方式来引用这个已保存好的正则对象
将引用变量插入到其它模式中构建更复杂的正则表达式
其中:
 
qr//的定界符斜线可以替换为其它符号,例如对称的括号类qr() qr{} qr<> qr[],一致的符号类qr%% qr## qr!! qr$$ qr"" qr''等。
但是使用单引号作为定界符时比较特殊(即qr'pattern'),它会将pattern部分使用单引号的方式去解析,例如变量$var无法替换,而是表示4个字符。但是正则表达式的元字符仍然起作用,例如$仍然表示行尾。
$str="hello worlds gaoxiaofang";
 
# 直接作为正则表达式
$str =~ qr/w.*d/;
print "$&\n";
 
# 保存为变量,再作为正则表达式
$pattern=qr/w.*d/;
$str =~ $pattern;    # (1)
$str =~ /$pattern/;  # (2)
print "$&\n";
 
# 保存为变量,作为正则表达式的一部分
$pattern=qr/w.*d/;
$str =~ /hel.* $pattern/;
print "$&\n";
 
还允许为这个正则对象设置修饰符,比如忽略大小写的匹配修饰符为i,这样在真正匹配的时候,就只有这一部分正则对象会忽略大小写,其余部分仍然区分大小写。
$str="HELLO wORLDs gaoxiaofang";
 
$pattern=qr/w.*d/i;        # 忽略大小写
 
$str =~ /HEL.* $pattern/;  # 匹配成功,$pattern部分忽略大小写
$str =~ /hel.* $pattern/;  # 匹配失败
$str =~ /hel.* $pattern/i;  # 匹配成功,所有都忽略大小写
 
qr如何构建正则对象
 
输出qr构建的正则引用,看看是怎样的结构:
$patt1=qr/w.*d/;
print "$patt1\n";
 
$patt2=qr/w.*d/i;    # 加上修饰符i
print "$patt2\n";
 
$patt3=qr/w.*d/img;  # 加上修饰符img
print "$patt3\n";
 
上面的print将输出如下结果:
(?^:w.*d)
(?^i:w.*d)
(?^mi:w.*d)
 
qr的作用实际上就是在我们给定的正则pattern基础上加上(?^:)并带上一些修饰符,得到的结果总是(?^FLAGS:pattern)。
 
但是上面patt3的修饰符g不见了。先可以看看(?^:)的作用:非捕获分组,并重置修饰符。重置为哪些修饰符?对于(?^FLAGS:)来说,只有这些修饰符"alupimsx"是可用的,即(?^alupimsx:):
 
如果给定的修饰符不在这些修饰符内,则不被识别,有时候会报错
如果给定的修饰符属于这几个修饰符,那么没有给定的修饰符部分将采用默认值(不同版本可能默认是否开启的值不同)
所以上面的g会被丢弃,甚至在进一步操作这个正则引用时,会报错。
 
既然qr给pattern部分加上了(?^:),那么当它们插入到其它正则中的时候,就能保证这一段是独立的,不受全局修饰符影响的模式。
$patt1=qr/w.*d/im;
$patt2=qr/hel.*d $patt1/i;
print "$patt2\n";    # 输出:(?^i:hel.*d (?^mi:w.*d))
 
正则引用作为标量的用法
 
既然qr//创建的正则对象引用是一个标量,那么标量可以出现的地方,正则引用就可以出现。例如,放进hash结构,数组结构。
 
例如,放进数组中形成一个正则表达式列表,然后给定一个待匹配目标,依次用列表中的这些模式去匹配。
use v5.10.1;
my @patterns = (
    qr/(?:Willie )?Gilligan/,
    qr/Mary Ann/,
    qr/Ginger/,
    qr/(?:The )?Professor/,
    qr/Skipper/,
    qr/Mrs?. Howell/,
);
 
my $name = 'Ginger';
foreach my $pattern ( @patterns ) {
    if( $name =~ /$pattern/ ) {
        say "Match!";
        print "$pattern";
        last;
    }
}
 
还可以将这些正则引用放进hash中,为每个pattern都使用key来标识一下,例如pattern1是用来匹配什么的:
use v5.10.1;
my %patterns = (
    Gilligan => qr/(?:Willie )?Gilligan/,
    'Mary Ann' => qr/Mary Ann/,
    Ginger => qr/Ginger/,
    Professor => qr/(?:The )?Professor/,
    Skipper => qr/Skipper/,
    'A Howell' => qr/Mrs?. Howell/,
);
my $name = 'Ginger';
my( $match ) = grep { $name =~ $patterns{$_} } keys %patterns;
say "Matched $match" if $match;
 
上面将grep语句的结果赋值给了一个标量,所以如果有多个Pattern能匹配$name,多次执行,$match的值将可能会不一样。
 
构建复杂的正则表达式
 
有了qr,就可以将正则表达式细化成一小片一小片,然后组合起来。例如:
my $howells = qr/Thurston|Mrs/;
my $tagalongs = qr/Ginger|Mary Ann/;
my $passengers = qr/$howells|$tagalongs/;
my $crew = qr/Gilligan|Skipper/;
my $everyone = qr/$crew|$passengers/;
 
就像RFC 1738中对URL各个部分的解剖,如果转换成Perl正则,大概是这样的(了解即可):
# 可复用的基本符号类
my $alpha = qr/[a−z]/;
my $digit = qr/\d/;
my $alphadigit = qr/(?i:$alpha|$digit)/;
my $safe = qr/[\$_.+−]/;
my $extra = qr/[!*'\(\),]/;
my $national = qr/[{}|\\^~\[\]`]/;
my $reserved = qr|[;/?:@&=]|;
my $hex = qr/(?i:$digit|[A−F])/;
my $escape = qr/%$hex$hex/;
my $unreserved = qr/$alpha|$digit|$safe|$extra/;
my $uchar = qr/$unreserved|$escape/;
my $xchar = qr/$unreserved|$reserved|$escape/;
my $ucharplus = qr/(?:$uchar|[;?&=])*/;
my $digits = qr/(?:$digit){1,}/;
 
# 可复用的URL组成元素
my $hsegment = $ucharplus;
my $hpath = qr|$hsegment(?:/$hsegment)*|;
my $search = $ucharplus;
my $scheme = qr|(?i:https?://)|;
my $port = qr/$digits/;
my $password = $ucharplus;
my $user = $ucharplus;

dawei

【声明】:九江站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。