Perl5学习笔记-第六章-模式匹配
一、简介
二、匹配操作符
三、模式中的特殊字符
1、字符+
2、字符 []和[^]
3、字符 *和?
4、转义字符
5、匹配任意字母或数字
6、锚模式
7、模式中的变量替换
8、字符范围转义前缀
9、匹配任意字符
10、匹配指定数目的字符
11、指定选项
12、模式的部分重用
13、转义和特定字符的执行次序
14、指定模式定界符
15、模式次序变量
四、模式匹配选项
1、匹配所有可能的模式(g选项)
2、忽略大小写(i选项)例
3、将字符串看作多行(m选项)
4、只执行一次变量替换例
5、将字符串看作单行例
6、在模式中忽略空格
五、替换操作符
六、转换操作符
七、扩展模式匹配
1、不存贮括号内的匹配内容
2、内嵌模式选项
3、肯定的和否定的预见匹配
4、模式注释
八、 注意贪婪性
九、正则表达式的返回值
一、简介
模式指在字符串中寻找的特定序列的字符,由反斜线包含:/def/即模式def。其用法如结合函数split将字符串用某模式分成多个单词:@array = split(/ /, $line);
运用正则表达式的基本方法是使用结合的经营模式=~和!~。第一个是一个测试操作符,第二是一个赋值操作符。
匹配正则表达式 - m//
替代正则表达式 - s///
直译(拼写)正则表达式 - tr///
二、匹配操作符 =~、!~
=~检验匹配是否成功:$result = $var =~ /abc/;若在该字符串中找到了该模式,则返回非零值,即true,不匹配则返回0,即false。!~则相反。这两个操作符适于条件控制中,如:
if($question =~ /please/){
print ("Thank you for being polite!\n");
}else{
print ("That was not very polite!\n");
}
三、模式中的特殊字符
Perl在模式中支持一些特殊字符,可以起到一些特殊的作用。
1、字符 +
+意味着一个或多个相同的字符,如:/de+f/指def、deef、deeeeef等。它尽量匹配尽可能多的相同字符,如/ab+/在字符串abbc中匹配的将是abb,而不是ab。当一行中各单词间的空格多于一个时,可以如下分割:@array = split (/ +/, $line);
注:split函数每次遇到分割模式,总是开始一个新单词,因此若$line以空格打头,则@array的第一个元素即为空元素。但其可以区分是否真有单词,如若$line中只有空格,则@array则为空数组。且上例中TAB字符被当作一个单词。注意修正。
2、字符 []和[^]
[]意味着匹配一组字符中的一个,如/a[0123456789]c/将匹配a加数字加c的字符串。与+联合使用例:/d[eE]+f/匹配def、 dEf、deef、dEef、dEEEeeeEef等。^表示除其之外的所有字符,如:/d[^deE]f/匹配d加非e字符加f的字符串。
3、字符 *和?
它们与+类似,区别在于*匹配0个、1个或多个相同字符,?匹配0个或1个该字符。如/de*f/匹配df、def、deeeef等;/de?f/匹配df或def。
4、转义字符
如果你想在模式中包含通常被看作特殊意义的字符,须在其前加斜线"\"。如:/\*+/中\*即表示字符*,而不是上面提到的一个或多个字符的含义。斜线的表示为/\\/。在Perl5中可用字符对\Q和\E来转义。
5、匹配任意字母或数字
上面提到模式/a[0123456789]c/匹配字母a加任意数字加c的字符串,另一种表示方法为:/a[0-9]c/,类似的,[a-z]表示任意小写字母,[A-Z]表示任意大写字母。任意大小写字母、数字的表示方法为:/[0-9a-zA-Z]/。
6、锚模式
锚 描述
^ 或 \A 仅匹配串首
$ 或 \Z 仅匹配串尾
\b 匹配单词边界
\B 单词内部匹配
例1:/^def/只匹配以def打头的字符串,/$def/只匹配以def结尾的字符串,结合起来的/^def$/只匹配字符串def(?)。\A和\Z在多行匹配时与^和$不同。
例2:检验变量名的类型:
if($varname =~ /^\$[A-Za-z][_0-9a-zA-Z]*$/){
print ("$varname is a legal scalar variable\n");
}elsif ($varname =~ /^@[A-Za-z][_0-9a-zA-Z]*$/){
print ("$varname is a legal array variable\n");
}elsif ($varname =~ /^[A-Za-z][_0-9a-zA-Z]*$/){
print ("$varname is a legal file variable\n");
}else{
print ("I don't understand what $varname is.\n");
}
例3:\b在单词边界匹配:/\bdef/匹配def和defghi等以def打头的单词,但不匹配abcdef。/def\b/匹配def和 abcdef等以def结尾的单词,但不匹配defghi,/\bdef\b/只匹配字符串def。注意:/\bdef/可匹配$defghi,因为$并不被看作是单词的部分。
例4:\B在单词内部匹配:/\Bdef/匹配abcdef等,但不匹配def;/def\B/匹配defghi等;/\Bdef\B/匹配cdefg、abcdefghi等,但不匹配def,defghi,abcdef。
7、模式中的变量替换
将句子分成单词:
$pattern = "[\\t ]+";
@words = split(/$pattern/, $line);
8、字符范围转义
转义字符 描述 范围
\d 任意数字 [0-9]
\D 除数字外的任意字符 [^0-9]
\w 任意单词字符 [_0-9a-zA-Z]
\W 任意非单词字符 [^_0-9a-zA-Z]
\s 空白 [ \r\t\n\f]
\S 非空白 [^ \r\t\n\f]
例:/[\da-z]/匹配任意数字或小写字母。
9、匹配任意字符
字符"."匹配除换行外的所有字符,通常与*合用。
10、匹配指定数目的字符
字符对{}指定所匹配字符的出现次数。如:/de{1,3}f/匹配def,deef和deeef;/de{3}f/匹配deeef;/de{3,}f/匹配不少于3个e在d和f之间;/de{0,3}f/匹配不多于3个e在d和f之间。
11、指定选项
字符"|"指定两个或多个选择来匹配模式。如:/def|ghi/匹配def或ghi。
例:检验数字表示合法性
if ($number =~ /^-?\d+$|^-?0[xX][\da-fa-F]+$/) {
print ("$number is a legal integer.\n");
}else{
print ("$number is not a legal integer.\n");
}
其中 ^-?\d+$ 匹配十进制数字,^-?0[xX][\da-fa-F]+$ 匹配十六进制数字。
12、模式的部分重用
当模式中匹配相同的部分出现多次时,可用括号括起来,用\n来多次引用,以简化表达式:/\d{2}([\W])\d{2}\1\d{2}/ 匹配:
12-05-92
26.11.87
07 04 92等
注意:/\d{2}([\W])\d{2}\1\d{2}/ 不同于/(\d{2})([\W])\1\2\1/ ,后者只匹配形如17-17-17的字符串,而不匹配17-05-91等。
13、转义和特定字符的执行次序
象操作符一样,转义和特定字符也有执行次序:
特殊字符 描述
() 模式内存
+ * ? {} 出现次数
^ $ \b \B 锚
| 选项
14、指定模式定界符
缺省的模式定界符为反斜线/,此时其操作字母m可省略;当用非反斜线/做为定界符时,则要在其前加字母m,如:
m!/u/jqpublic/Perl/prog1! 等价于/\/u\/jqpublic\/Perl\/prog1/
注:当用字母'作为定界符时,不做变量替换;当用特殊字符作为定界符时,其转义功能或特殊功能即不能使用。一般不用担心出现在模式内的定界符,因其是成对出现的,即使其中含有引号;但尖括号(<与>)不是正则表达式的元字符,所以它们不可能成对出现,因此使用其时需要在其前加了反斜线来转义或使用其它符号来定界。
15、模式次序变量
在模式匹配后调用重用部分的结果可用变量$n,全部的结果用变量$&。
$string = "This string contains the number 25.11.";
$string =~ /-?(\d+)\.?(\d+)/; # 匹配结果为25.11
$integerpart = $1; # now $integerpart = 25
$decimalpart = $2; # now $decimalpart = 11
$totalpart = $&; # now totalpart = 25.11
四、模式匹配选项(运算符修饰符)
选项 描述
g 匹配所有可能的模式
i 忽略大小写
m 将串视为多行
o 只赋值一次
s 将串视为单行
x 忽略模式中的空白
匹配的操作符支持其自己的一套修饰符,/g的修饰符,使全局匹配,/i修饰符将匹配不区分大小写。这里是完整的修饰符列表:
Modifier Description
i Makes the match case insensitive
m Specifies that if the string has newline or carriage return characters, the ^ and $ operators will now match against a newline boundary, instead of a string boundary
o Evaluates the expression only once
s Allows use of . to match a newline character
x Allows you to use white space in the expression for clarity
g Globally finds all matches
cg Allows the search to continue even after a global match fails
1、匹配所有可能的模式(g选项)
@matches = "balata" =~ /.a/g; # now @matches = ("ba", "la", "ta")
匹配的循环:
while ("balata" =~ /.a/g) {
$match = $&;
print ("$match\n");
}
结果为:
ba
la
ta
当使用了选项g时,可用函数pos来控制下次匹配的偏移:
$offset = pos($string);
pos($string) = $newoffset;
2、忽略大小写(i选项)例
/de/i 匹配de,dE,De和DE。
3、将字符串看作多行(m选项)
在此情况下,^符号匹配字符串的起始或新的一行的起始;$符号匹配任意行的末尾。
4、只执行一次变量替换例
$var = 1;
$line = <>; while ($var < 10) {$result = $line =~ /$var/o; $line = ; $var++;} 每次均匹配/1/。
5、将字符串看作单行,例 /a.*bc/s匹配字符串axxxxx \nxxxxbc,但/a.*bc/则不匹配该字符串。
6、在模式中忽略空格 /\d{2} ([\W]) \d{2} \1 \d{2}/x等价于/\d{2}([\W])\d{2}\1\d{2}/。
五、替换操作符
语法为s/pattern/replacement/,其效果为将字符串中与pattern匹配的部分换成replacement。如:
$string = "abc123def";
$string =~ s/123/456/; # now $string = "abc456def";
在替换部分可使用模式次序变量$n,如s/(\d+)/[$1]/,但在替换部分不支持模式的特殊字符,如{},*,+等,如s/abc/[def]/将把abc替换为[def]。
替换操作符的选项如下表:
选项 描述
g 改变模式中的所有匹配
i 忽略模式中的大小写
e 替换字符串作为表达式
m 将待匹配串视为多行
o 仅赋值一次
s 将待匹配串视为单行
x 忽略模式中的空白
替代操作符的所有修改的列表:
Modifier Description
i Makes the match case insensitive
m Specifies that if the string has newline or carriage return characters, the ^ and $ operators will now match against a newline boundary, instead of a string boundary
o Evaluates the expression only once
s Allows use of . to match a newline character
x Allows you to use white space in the expression for clarity
g Replaces all occurrences of the found expression with the replacement text
e Evaluates the replacement as if it were a Perl statement,and uses its return value as the replacement text
注:e选项把替换部分的字符串看作表达式,在替换之前先计算其值,如:
$string = "0abc1";
$string =~ s/[a-zA-Z]+/$& x 2/e; # now $string = "0abcabc1"
六、转换操作符
这是另一种替换方式,语法如:tr/string1/string2/。同样,string2为替换部分,但其效果是把string1中的第一个字符替换为string2中的第一个字符,把string1中的第二个字符替换为string2中的第二个字符,依此类推。如:
$string = "abcdefghicba";
$string =~ tr/abc/def/; # now string = "defdefghifed"
当string1比string2长时,其多余字符替换为string2的最后一个字符;当string1中同一个字符出现多次时,将使用第一个替换字符。
注意:tr并非真正意义上的正则,因此有部分转义符在此是不能正常使用的,只能写出其非转义的等值替代。如\d用[0-9]平替,\t可以用但\s无法使用。
转换操作符的选项如下:
选项 描述
c 翻译所有未指定字符
d 删除找到但未替换的字符
s 把多个相同的输出字符缩成一个
有关操作符的运算符名单
Modifier Description
c Complement SEARCHLIST.
d Delete found but unreplaced characters.
s Squash duplicate replaced characters.
如:$string =~ tr/[^0-9]/ /c:把所有非数字字符替换为空格;
$string =~ tr/\t //d:删除Tab;
$string =~ tr/0-9/ /cs:把数字间的其它字符替换为一个空格。
tr/a-zA-Z//s # bookkeeper -> bokeper
七、扩展模式匹配
Perl支持Perl4和标准UNIX模式匹配操作所没有的一些模式匹配能力,其语法为:(?pattern),其中c是一个字符,pattern是起作用的模式或子模式。
1、不存贮括号内的匹配内容 在Perl的模式中,括号内的子模式将存贮在内存中,此功能即取消存贮该括号内的匹配内容,如/(?:a|b|c)(d|e)f\1/中的\1表示已匹配的d或e,而不是a或b或c。
2、内嵌模式选项 通常模式选项置于其后,有四个选项:i、m、s、x可以内嵌使用,语法为:/(?option)pattern/,等价于/pattern/option。
3、肯定的和否定的预见匹配 肯定的预见匹配语法为/pattern(?=string)/,其意义为匹配后面为string的模式,相反的,(?!string)意义为匹配后面非string的模式,如:$string = "25abc8"; $string =~ /abc(?=[0-9])/; $matched = $&; # $&为已匹配的模式,此处为abc,而不是abc8
4、模式注释
Perl5中可以在模式中用?#来加注释,如:if ($string =~ /(?i)[a-z]{2,3}(?# match two or three alphabetic characters)/ { ... }
现以简表总结如下:
1)、文字处理模式中,/pattern/常用到的语法
v5.10起支持的正则字符集
\h 水平空白字符
\H 非水平空白字符
\v 垂直空白字符
\V 非垂直空白字符
\R 广义行尾字符
\N 非换行符(v5.18起稳定)
2)、文字处理模式(Regular Expression)的简单范例
看了上一小节文字处理模(Regular Expression)之的初学者对于这个语法的应用可能还不是很清楚,所以笔者会在这一小节中举出一些在文字处理模式中常用的范例:
/Perl/
找到含有Perl的字符串
/^Perl/
找到开头是Perl的字符串
/Perl$/
找到结尾是Perl的字符串
/c|g|i/
找到含有c或g或i的字符串
/cg{2,4}i/
找到c后面跟着2个到4个g,再跟着i的字符串
/cg{2,}i/
找到c后面跟着2个以上g,再跟着i的字符串
/cg{2}i/
找到c后面跟着2个g,再跟着i的字符串
/cg*i/
找到c后面跟着0个或多个g,再跟着i的字符串,如同/cg{0,1}i/
/cg+i/
找到c后面跟着一个以上g,再跟着c的字符串,如同/cg{1,}i/
/cg?i/
找到c后面跟着0个或是一个g,再跟着c的字符串,如同/cg{0,1}i/
/c.i/
找到c后面跟着一个任意字符,再跟着i的字符串
/c..i/
找到c后面跟着二个任意字符,再跟着i的字符串
/[cgi]/
找到符合有这三个字符任意一个的字符串
/[^cgi]/
找到没有这三个字符中任意一个的字符串
/\d/
找寻符合数值的字符串,可以使用/\d+/来表示一个或是多个数值的字符串
/\D/
找寻符合不是数值的字符串,可以使用/\D+/来表示一个或是更多个非数值的字符串
/\w/
找寻符合英文字母,数值的字符串,可以使用/\w+/来表示一个或是更多个英文字母,数值的字符串
/\W/
找寻符合非英文字母,数值字符的字符串,可以使用/\W+/来表示一个或是更多个非英文字母,数值的字符串
/\s/
找寻符合空白的字符串,可以使用/\s+/来表示一个或是更多个空白字符的字符串
/\S/
找寻符合不是空白的字符串,可以使用/\S+/来表示一个或是更多不是空白的字符的字符串
/\*/
找寻符合*这个符号的字符串,因为*在文字处理模式中有它的特殊意思,所以要在这个特殊符号前加上\这个符号,这样才会让这个特殊字符失效
/abc/i
找寻符合abc的字符串而且不考虑这些符合字符串的大小写
3)、文字处理模式(Regular Expresion)相关的运算符及函数
在Perl程序写作中常会用到=~和!~这两个运算符及s和t这二个函数来和文字处理模式/pattern/搭配而成一个运算式,如果能够活用这些指令的话就可以很轻易地来处理一些字符串,当然在CGI程序设计中了就更能得心应手了。
八、注意贪婪性
假设你想用一个正则表达式匹配一个HTML标签。你知道输入将会是一个有效的HTML文件,因此正则表达式不需要排除那些无效的标签。所以如果是在两个尖括号之间的内容,就应该是一个HTML标签。
许多正则表达式的新手会首先想到用正则表达式<< <.+> >>,他们会很惊讶的发现,对于测试字符串,"This is a <EM>first</EM> test",你可能期望会返回<EM>,然后继续进行匹配的时候,返回</EM>。
但事实是不会。正则表达式将会匹配"<EM>first</EM>"。很显然这不是我们想要的结果。原因在于"+"是贪婪的。也就是说,"+"会导致正则表达式引擎试图尽可能的重复前导字符。只有当这种重复会引起整个正则表达式匹配失败的情况下,引擎会进行回溯。也就是说,它会放弃最后一次的"重复",然后处理正则表达式余下的部分。
和"+"类似,"?*"的重复也是贪婪的。
用懒惰性取代贪婪性
一个用于修正以上问题的可能方案是用"+"的惰性代替贪婪性。你可以在"+"后面紧跟一个问号"?"来达到这一点。"*","{}"和"?"表示的重复也可以用这个方案。因此在上面的例子中我们可以使用"<.+?>"。让我们再来看看正则表达式引擎的处理过程。
再一次,正则表达式记号"<"会匹配字符串的第一个"<"。下一个正则记号是"."。这次是一个懒惰的"+"来重复上一个字符。这告诉正则引擎,尽可能少的重复上一个字符。因此引擎匹配"."和字符"E",然后用">"匹配"M",结果失败了。引擎会进行回溯,和上一个例子不同,因为是惰性重复,所以引擎是扩展惰性重复而不是减少,于是"<.+"现在被扩展为"<EM"。引擎继续匹配下一个记号">"。这次得到了一个成功匹配。引擎于是报告"<EM>"是一个成功的匹配。整个过程大致如此。
惰性扩展的一个替代方案
还有一个更好的替代方案。可以用一个贪婪重复与一个取反字符集:"<[^>]+>"。
九、正则表达式的返回值
(正则表达式匹配后返回的为数组或长度,取决于表达式中是否有()或者接收的变量类型)
$a = 'RRR3ttt';
@yy = $a=~/RRR.*ttt/;
$numofyy = $a=~/RRR.*ttt/;
print "@yy\n";
print "$numofyy\n" ;
@yy2 = $a=~/(RRR).*(ttt)/;
$numofyy2 = $a=~/(RRR).*(ttt)/;
print "@yy2\n";
print "$numofyy2\n";
print "$1 $2";
结果:
1
1
RRR ttt
1
RRR ttt
模式内圆括号匹配到的字符串会被返回到目标数组
my $t='I like the freeoa site 15 years from year 2009';
my @ws=($t=~/[a-z]+/ig); #@ws is:I like the freeoa site years from year
相当于split的逆运算,正则模式是要留下想要的部分。亦可构建Hash:
my $ht='ka va kb vb kc vc';
my %ht=($ht=~/(\w+)\s(\w+)/g);
分组匹配
从一个角度的正则表达式看没有区别,也许前者是稍微更清晰。
$string =~ /(\S+)\s+(\S+)/;
and
$string =~ /\S+\s+\S+/;
然而,在分组的好处是,它使我们能够从一个正则表达式提取序列。返回一个列表的顺序,在他们出现在原来的分组。例如,在下面的片段中,我们已经从一个字符串取出小时,分钟和秒:
my ($hours,$minutes,$seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
除了这种直接的方法,也可以在特殊的$x变量,其中x是该组内一些正则表达式匹配组。因此,我们可以重写前面的例子如下:
$time =~ m/(\d+):(\d+):(\d+)/;
my ($hours, $minutes, $seconds) = ($1,$2,$3);
二、匹配操作符
三、模式中的特殊字符
1、字符+
2、字符 []和[^]
3、字符 *和?
4、转义字符
5、匹配任意字母或数字
6、锚模式
7、模式中的变量替换
8、字符范围转义前缀
9、匹配任意字符
10、匹配指定数目的字符
11、指定选项
12、模式的部分重用
13、转义和特定字符的执行次序
14、指定模式定界符
15、模式次序变量
四、模式匹配选项
1、匹配所有可能的模式(g选项)
2、忽略大小写(i选项)例
3、将字符串看作多行(m选项)
4、只执行一次变量替换例
5、将字符串看作单行例
6、在模式中忽略空格
五、替换操作符
六、转换操作符
七、扩展模式匹配
1、不存贮括号内的匹配内容
2、内嵌模式选项
3、肯定的和否定的预见匹配
4、模式注释
八、 注意贪婪性
九、正则表达式的返回值
一、简介
模式指在字符串中寻找的特定序列的字符,由反斜线包含:/def/即模式def。其用法如结合函数split将字符串用某模式分成多个单词:@array = split(/ /, $line);
运用正则表达式的基本方法是使用结合的经营模式=~和!~。第一个是一个测试操作符,第二是一个赋值操作符。
匹配正则表达式 - m//
替代正则表达式 - s///
直译(拼写)正则表达式 - tr///
二、匹配操作符 =~、!~
=~检验匹配是否成功:$result = $var =~ /abc/;若在该字符串中找到了该模式,则返回非零值,即true,不匹配则返回0,即false。!~则相反。这两个操作符适于条件控制中,如:
if($question =~ /please/){
print ("Thank you for being polite!\n");
}else{
print ("That was not very polite!\n");
}
三、模式中的特殊字符
Perl在模式中支持一些特殊字符,可以起到一些特殊的作用。
1、字符 +
+意味着一个或多个相同的字符,如:/de+f/指def、deef、deeeeef等。它尽量匹配尽可能多的相同字符,如/ab+/在字符串abbc中匹配的将是abb,而不是ab。当一行中各单词间的空格多于一个时,可以如下分割:@array = split (/ +/, $line);
注:split函数每次遇到分割模式,总是开始一个新单词,因此若$line以空格打头,则@array的第一个元素即为空元素。但其可以区分是否真有单词,如若$line中只有空格,则@array则为空数组。且上例中TAB字符被当作一个单词。注意修正。
2、字符 []和[^]
[]意味着匹配一组字符中的一个,如/a[0123456789]c/将匹配a加数字加c的字符串。与+联合使用例:/d[eE]+f/匹配def、 dEf、deef、dEef、dEEEeeeEef等。^表示除其之外的所有字符,如:/d[^deE]f/匹配d加非e字符加f的字符串。
3、字符 *和?
它们与+类似,区别在于*匹配0个、1个或多个相同字符,?匹配0个或1个该字符。如/de*f/匹配df、def、deeeef等;/de?f/匹配df或def。
4、转义字符
如果你想在模式中包含通常被看作特殊意义的字符,须在其前加斜线"\"。如:/\*+/中\*即表示字符*,而不是上面提到的一个或多个字符的含义。斜线的表示为/\\/。在Perl5中可用字符对\Q和\E来转义。
5、匹配任意字母或数字
上面提到模式/a[0123456789]c/匹配字母a加任意数字加c的字符串,另一种表示方法为:/a[0-9]c/,类似的,[a-z]表示任意小写字母,[A-Z]表示任意大写字母。任意大小写字母、数字的表示方法为:/[0-9a-zA-Z]/。
6、锚模式
锚 描述
^ 或 \A 仅匹配串首
$ 或 \Z 仅匹配串尾
\b 匹配单词边界
\B 单词内部匹配
例1:/^def/只匹配以def打头的字符串,/$def/只匹配以def结尾的字符串,结合起来的/^def$/只匹配字符串def(?)。\A和\Z在多行匹配时与^和$不同。
例2:检验变量名的类型:
if($varname =~ /^\$[A-Za-z][_0-9a-zA-Z]*$/){
print ("$varname is a legal scalar variable\n");
}elsif ($varname =~ /^@[A-Za-z][_0-9a-zA-Z]*$/){
print ("$varname is a legal array variable\n");
}elsif ($varname =~ /^[A-Za-z][_0-9a-zA-Z]*$/){
print ("$varname is a legal file variable\n");
}else{
print ("I don't understand what $varname is.\n");
}
例3:\b在单词边界匹配:/\bdef/匹配def和defghi等以def打头的单词,但不匹配abcdef。/def\b/匹配def和 abcdef等以def结尾的单词,但不匹配defghi,/\bdef\b/只匹配字符串def。注意:/\bdef/可匹配$defghi,因为$并不被看作是单词的部分。
例4:\B在单词内部匹配:/\Bdef/匹配abcdef等,但不匹配def;/def\B/匹配defghi等;/\Bdef\B/匹配cdefg、abcdefghi等,但不匹配def,defghi,abcdef。
7、模式中的变量替换
将句子分成单词:
$pattern = "[\\t ]+";
@words = split(/$pattern/, $line);
8、字符范围转义
转义字符 描述 范围
\d 任意数字 [0-9]
\D 除数字外的任意字符 [^0-9]
\w 任意单词字符 [_0-9a-zA-Z]
\W 任意非单词字符 [^_0-9a-zA-Z]
\s 空白 [ \r\t\n\f]
\S 非空白 [^ \r\t\n\f]
例:/[\da-z]/匹配任意数字或小写字母。
9、匹配任意字符
字符"."匹配除换行外的所有字符,通常与*合用。
10、匹配指定数目的字符
字符对{}指定所匹配字符的出现次数。如:/de{1,3}f/匹配def,deef和deeef;/de{3}f/匹配deeef;/de{3,}f/匹配不少于3个e在d和f之间;/de{0,3}f/匹配不多于3个e在d和f之间。
11、指定选项
字符"|"指定两个或多个选择来匹配模式。如:/def|ghi/匹配def或ghi。
例:检验数字表示合法性
if ($number =~ /^-?\d+$|^-?0[xX][\da-fa-F]+$/) {
print ("$number is a legal integer.\n");
}else{
print ("$number is not a legal integer.\n");
}
其中 ^-?\d+$ 匹配十进制数字,^-?0[xX][\da-fa-F]+$ 匹配十六进制数字。
12、模式的部分重用
当模式中匹配相同的部分出现多次时,可用括号括起来,用\n来多次引用,以简化表达式:/\d{2}([\W])\d{2}\1\d{2}/ 匹配:
12-05-92
26.11.87
07 04 92等
注意:/\d{2}([\W])\d{2}\1\d{2}/ 不同于/(\d{2})([\W])\1\2\1/ ,后者只匹配形如17-17-17的字符串,而不匹配17-05-91等。
13、转义和特定字符的执行次序
象操作符一样,转义和特定字符也有执行次序:
特殊字符 描述
() 模式内存
+ * ? {} 出现次数
^ $ \b \B 锚
| 选项
14、指定模式定界符
缺省的模式定界符为反斜线/,此时其操作字母m可省略;当用非反斜线/做为定界符时,则要在其前加字母m,如:
m!/u/jqpublic/Perl/prog1! 等价于/\/u\/jqpublic\/Perl\/prog1/
注:当用字母'作为定界符时,不做变量替换;当用特殊字符作为定界符时,其转义功能或特殊功能即不能使用。一般不用担心出现在模式内的定界符,因其是成对出现的,即使其中含有引号;但尖括号(<与>)不是正则表达式的元字符,所以它们不可能成对出现,因此使用其时需要在其前加了反斜线来转义或使用其它符号来定界。
15、模式次序变量
在模式匹配后调用重用部分的结果可用变量$n,全部的结果用变量$&。
$string = "This string contains the number 25.11.";
$string =~ /-?(\d+)\.?(\d+)/; # 匹配结果为25.11
$integerpart = $1; # now $integerpart = 25
$decimalpart = $2; # now $decimalpart = 11
$totalpart = $&; # now totalpart = 25.11
四、模式匹配选项(运算符修饰符)
选项 描述
g 匹配所有可能的模式
i 忽略大小写
m 将串视为多行
o 只赋值一次
s 将串视为单行
x 忽略模式中的空白
匹配的操作符支持其自己的一套修饰符,/g的修饰符,使全局匹配,/i修饰符将匹配不区分大小写。这里是完整的修饰符列表:
Modifier Description
i Makes the match case insensitive
m Specifies that if the string has newline or carriage return characters, the ^ and $ operators will now match against a newline boundary, instead of a string boundary
o Evaluates the expression only once
s Allows use of . to match a newline character
x Allows you to use white space in the expression for clarity
g Globally finds all matches
cg Allows the search to continue even after a global match fails
1、匹配所有可能的模式(g选项)
@matches = "balata" =~ /.a/g; # now @matches = ("ba", "la", "ta")
匹配的循环:
while ("balata" =~ /.a/g) {
$match = $&;
print ("$match\n");
}
结果为:
ba
la
ta
当使用了选项g时,可用函数pos来控制下次匹配的偏移:
$offset = pos($string);
pos($string) = $newoffset;
2、忽略大小写(i选项)例
/de/i 匹配de,dE,De和DE。
3、将字符串看作多行(m选项)
在此情况下,^符号匹配字符串的起始或新的一行的起始;$符号匹配任意行的末尾。
4、只执行一次变量替换例
$var = 1;
$line = <>; while ($var < 10) {$result = $line =~ /$var/o; $line = ; $var++;} 每次均匹配/1/。
5、将字符串看作单行,例 /a.*bc/s匹配字符串axxxxx \nxxxxbc,但/a.*bc/则不匹配该字符串。
6、在模式中忽略空格 /\d{2} ([\W]) \d{2} \1 \d{2}/x等价于/\d{2}([\W])\d{2}\1\d{2}/。
五、替换操作符
语法为s/pattern/replacement/,其效果为将字符串中与pattern匹配的部分换成replacement。如:
$string = "abc123def";
$string =~ s/123/456/; # now $string = "abc456def";
在替换部分可使用模式次序变量$n,如s/(\d+)/[$1]/,但在替换部分不支持模式的特殊字符,如{},*,+等,如s/abc/[def]/将把abc替换为[def]。
替换操作符的选项如下表:
选项 描述
g 改变模式中的所有匹配
i 忽略模式中的大小写
e 替换字符串作为表达式
m 将待匹配串视为多行
o 仅赋值一次
s 将待匹配串视为单行
x 忽略模式中的空白
替代操作符的所有修改的列表:
Modifier Description
i Makes the match case insensitive
m Specifies that if the string has newline or carriage return characters, the ^ and $ operators will now match against a newline boundary, instead of a string boundary
o Evaluates the expression only once
s Allows use of . to match a newline character
x Allows you to use white space in the expression for clarity
g Replaces all occurrences of the found expression with the replacement text
e Evaluates the replacement as if it were a Perl statement,and uses its return value as the replacement text
注:e选项把替换部分的字符串看作表达式,在替换之前先计算其值,如:
$string = "0abc1";
$string =~ s/[a-zA-Z]+/$& x 2/e; # now $string = "0abcabc1"
六、转换操作符
这是另一种替换方式,语法如:tr/string1/string2/。同样,string2为替换部分,但其效果是把string1中的第一个字符替换为string2中的第一个字符,把string1中的第二个字符替换为string2中的第二个字符,依此类推。如:
$string = "abcdefghicba";
$string =~ tr/abc/def/; # now string = "defdefghifed"
当string1比string2长时,其多余字符替换为string2的最后一个字符;当string1中同一个字符出现多次时,将使用第一个替换字符。
注意:tr并非真正意义上的正则,因此有部分转义符在此是不能正常使用的,只能写出其非转义的等值替代。如\d用[0-9]平替,\t可以用但\s无法使用。
转换操作符的选项如下:
选项 描述
c 翻译所有未指定字符
d 删除找到但未替换的字符
s 把多个相同的输出字符缩成一个
有关操作符的运算符名单
Modifier Description
c Complement SEARCHLIST.
d Delete found but unreplaced characters.
s Squash duplicate replaced characters.
如:$string =~ tr/[^0-9]/ /c:把所有非数字字符替换为空格;
$string =~ tr/\t //d:删除Tab;
$string =~ tr/0-9/ /cs:把数字间的其它字符替换为一个空格。
tr/a-zA-Z//s # bookkeeper -> bokeper
七、扩展模式匹配
Perl支持Perl4和标准UNIX模式匹配操作所没有的一些模式匹配能力,其语法为:(?pattern),其中c是一个字符,pattern是起作用的模式或子模式。
1、不存贮括号内的匹配内容 在Perl的模式中,括号内的子模式将存贮在内存中,此功能即取消存贮该括号内的匹配内容,如/(?:a|b|c)(d|e)f\1/中的\1表示已匹配的d或e,而不是a或b或c。
2、内嵌模式选项 通常模式选项置于其后,有四个选项:i、m、s、x可以内嵌使用,语法为:/(?option)pattern/,等价于/pattern/option。
3、肯定的和否定的预见匹配 肯定的预见匹配语法为/pattern(?=string)/,其意义为匹配后面为string的模式,相反的,(?!string)意义为匹配后面非string的模式,如:$string = "25abc8"; $string =~ /abc(?=[0-9])/; $matched = $&; # $&为已匹配的模式,此处为abc,而不是abc8
4、模式注释
Perl5中可以在模式中用?#来加注释,如:if ($string =~ /(?i)[a-z]{2,3}(?# match two or three alphabetic characters)/ { ... }
现以简表总结如下:
1)、文字处理模式中,/pattern/常用到的语法
| 表达式 | 描述 |
|---|---|
| . | 匹配除换行符以外的所有字符 |
| x? | 匹配 0 次或一次 x 字符串 |
| x* | 匹配 0 次或多次 x 字符串,但匹配可能的最少次数 |
| x+ | 匹配 1 次或多次 x 字符串,但匹配可能的最少次数 |
| .* | 匹配 0 次或多次的任何字符 |
| .+ | 匹配 1 次或多次的任何字符 |
| {m} | 匹配刚好是 m 个 的指定字符串 |
| {m,n} | 匹配在 m个 以上 n个 以下 的指定字符串 |
| {m,} | 匹配 m个 以上 的指定字符串 |
| [] | 匹配符合 [] 内的字符 |
| [^] | 匹配不符合 [] 内的字符 |
| [0-9] | 匹配所有数字字符 |
| [a-z] | 匹配所有小写字母字符 |
| [^0-9] | 匹配所有非数字字符 |
| [^a-z] | 匹配所有非小写字母字符 |
| ^ | 匹配字符开头的字符 |
| $ | 匹配字符结尾的字符 |
| \d | 匹配一个数字的字符,和 [0-9] 语法一样 |
| \d+ | 匹配多个数字字符串,和 [0-9]+ 语法一样 |
| \D | 非数字,其他同 \d |
| \D+ | 非数字,其他同 \d+ |
| \w | 英文字母或数字的字符串,和 [a-zA-Z0-9_] 语法一样 |
| \w+ | 和 [a-zA-Z0-9_]+ 语法一样 |
| \W | 非英文字母或数字的字符串,和 [^a-zA-Z0-9_] 语法一样 |
| \W+ | 和 [^a-zA-Z0-9_]+ 语法一样 |
| \s | 空格,和 [\n\t\r\f] 语法一样 |
| \s+ | 和 [\n\t\r\f]+ 一样 |
| \S | 非空格,和 [^\n\t\r\f] 语法一样 |
| \S+ | 和 [^\n\t\r\f]+ 语法一样 |
| \b | 匹配以英文字母,数字为边界的字符串 |
| \B | 匹配不以英文字母,数值为边界的字符串 |
| a|b|c | 匹配符合a字符 或是b字符 或是c字符 的字符串 |
| abc | 匹配含有 abc 的字符串(pattern) () 这个符号会记住所找寻到的字符串,是一个很实用的语法。第一个 () 内所找到的字符串变成 $1 这个变量或是 \1 变量,第二个 () 内所找到的字符串变成 $2 这个变量或是 \2 变量,以此类推下去 |
| /pattern/i | i 这个参数表示忽略英文大小写,也就是在匹配字符串的时候,不考虑英文的大小写问题。\ 如果要在 pattern 模式中找寻一个特殊字符,如 "*",则要在这个字符前加上 \ 符号,这样才会让特殊字符失效 |
v5.10起支持的正则字符集
\h 水平空白字符
\H 非水平空白字符
\v 垂直空白字符
\V 非垂直空白字符
\R 广义行尾字符
\N 非换行符(v5.18起稳定)
2)、文字处理模式(Regular Expression)的简单范例
看了上一小节文字处理模(Regular Expression)之的初学者对于这个语法的应用可能还不是很清楚,所以笔者会在这一小节中举出一些在文字处理模式中常用的范例:
/Perl/
找到含有Perl的字符串
/^Perl/
找到开头是Perl的字符串
/Perl$/
找到结尾是Perl的字符串
/c|g|i/
找到含有c或g或i的字符串
/cg{2,4}i/
找到c后面跟着2个到4个g,再跟着i的字符串
/cg{2,}i/
找到c后面跟着2个以上g,再跟着i的字符串
/cg{2}i/
找到c后面跟着2个g,再跟着i的字符串
/cg*i/
找到c后面跟着0个或多个g,再跟着i的字符串,如同/cg{0,1}i/
/cg+i/
找到c后面跟着一个以上g,再跟着c的字符串,如同/cg{1,}i/
/cg?i/
找到c后面跟着0个或是一个g,再跟着c的字符串,如同/cg{0,1}i/
/c.i/
找到c后面跟着一个任意字符,再跟着i的字符串
/c..i/
找到c后面跟着二个任意字符,再跟着i的字符串
/[cgi]/
找到符合有这三个字符任意一个的字符串
/[^cgi]/
找到没有这三个字符中任意一个的字符串
/\d/
找寻符合数值的字符串,可以使用/\d+/来表示一个或是多个数值的字符串
/\D/
找寻符合不是数值的字符串,可以使用/\D+/来表示一个或是更多个非数值的字符串
/\w/
找寻符合英文字母,数值的字符串,可以使用/\w+/来表示一个或是更多个英文字母,数值的字符串
/\W/
找寻符合非英文字母,数值字符的字符串,可以使用/\W+/来表示一个或是更多个非英文字母,数值的字符串
/\s/
找寻符合空白的字符串,可以使用/\s+/来表示一个或是更多个空白字符的字符串
/\S/
找寻符合不是空白的字符串,可以使用/\S+/来表示一个或是更多不是空白的字符的字符串
/\*/
找寻符合*这个符号的字符串,因为*在文字处理模式中有它的特殊意思,所以要在这个特殊符号前加上\这个符号,这样才会让这个特殊字符失效
/abc/i
找寻符合abc的字符串而且不考虑这些符合字符串的大小写
3)、文字处理模式(Regular Expresion)相关的运算符及函数
在Perl程序写作中常会用到=~和!~这两个运算符及s和t这二个函数来和文字处理模式/pattern/搭配而成一个运算式,如果能够活用这些指令的话就可以很轻易地来处理一些字符串,当然在CGI程序设计中了就更能得心应手了。
八、注意贪婪性
假设你想用一个正则表达式匹配一个HTML标签。你知道输入将会是一个有效的HTML文件,因此正则表达式不需要排除那些无效的标签。所以如果是在两个尖括号之间的内容,就应该是一个HTML标签。
许多正则表达式的新手会首先想到用正则表达式<< <.+> >>,他们会很惊讶的发现,对于测试字符串,"This is a <EM>first</EM> test",你可能期望会返回<EM>,然后继续进行匹配的时候,返回</EM>。
但事实是不会。正则表达式将会匹配"<EM>first</EM>"。很显然这不是我们想要的结果。原因在于"+"是贪婪的。也就是说,"+"会导致正则表达式引擎试图尽可能的重复前导字符。只有当这种重复会引起整个正则表达式匹配失败的情况下,引擎会进行回溯。也就是说,它会放弃最后一次的"重复",然后处理正则表达式余下的部分。
和"+"类似,"?*"的重复也是贪婪的。
用懒惰性取代贪婪性
一个用于修正以上问题的可能方案是用"+"的惰性代替贪婪性。你可以在"+"后面紧跟一个问号"?"来达到这一点。"*","{}"和"?"表示的重复也可以用这个方案。因此在上面的例子中我们可以使用"<.+?>"。让我们再来看看正则表达式引擎的处理过程。
再一次,正则表达式记号"<"会匹配字符串的第一个"<"。下一个正则记号是"."。这次是一个懒惰的"+"来重复上一个字符。这告诉正则引擎,尽可能少的重复上一个字符。因此引擎匹配"."和字符"E",然后用">"匹配"M",结果失败了。引擎会进行回溯,和上一个例子不同,因为是惰性重复,所以引擎是扩展惰性重复而不是减少,于是"<.+"现在被扩展为"<EM"。引擎继续匹配下一个记号">"。这次得到了一个成功匹配。引擎于是报告"<EM>"是一个成功的匹配。整个过程大致如此。
惰性扩展的一个替代方案
还有一个更好的替代方案。可以用一个贪婪重复与一个取反字符集:"<[^>]+>"。
九、正则表达式的返回值
(正则表达式匹配后返回的为数组或长度,取决于表达式中是否有()或者接收的变量类型)
$a = 'RRR3ttt';
@yy = $a=~/RRR.*ttt/;
$numofyy = $a=~/RRR.*ttt/;
print "@yy\n";
print "$numofyy\n" ;
@yy2 = $a=~/(RRR).*(ttt)/;
$numofyy2 = $a=~/(RRR).*(ttt)/;
print "@yy2\n";
print "$numofyy2\n";
print "$1 $2";
结果:
1
1
RRR ttt
1
RRR ttt
模式内圆括号匹配到的字符串会被返回到目标数组
my $t='I like the freeoa site 15 years from year 2009';
my @ws=($t=~/[a-z]+/ig); #@ws is:I like the freeoa site years from year
相当于split的逆运算,正则模式是要留下想要的部分。亦可构建Hash:
my $ht='ka va kb vb kc vc';
my %ht=($ht=~/(\w+)\s(\w+)/g);
分组匹配
从一个角度的正则表达式看没有区别,也许前者是稍微更清晰。
$string =~ /(\S+)\s+(\S+)/;
and
$string =~ /\S+\s+\S+/;
然而,在分组的好处是,它使我们能够从一个正则表达式提取序列。返回一个列表的顺序,在他们出现在原来的分组。例如,在下面的片段中,我们已经从一个字符串取出小时,分钟和秒:
my ($hours,$minutes,$seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
除了这种直接的方法,也可以在特殊的$x变量,其中x是该组内一些正则表达式匹配组。因此,我们可以重写前面的例子如下:
$time =~ m/(\d+):(\d+):(\d+)/;
my ($hours, $minutes, $seconds) = ($1,$2,$3);