正则表达式详解(Perl)

定义:正则表达式是一种字符串模式,可用来和字符串进行匹配。匹配可能成功,也可能失败。许多UNIX命令,包括grep, sed, awk, ed, vi, emacs都有正则表达式的功能。Perl也有这种功能。Python也具有这种功能。
简单示例
例如:
grep abd readme.file > result.tx t
则Perl中,写成
if(/abc/)
{
 print $_;
}
在Perl中,正则表达式用斜线标记,以代表斜线之间的内容是个正则表达式。当表达式北斜线包围时,Perl会拿$_和它作比较,以判断条件的真假。
   while(<>) {
if (/abc/) {
    print $_;
}
}
这个程序片断能读入某文件的所有内容,并进行匹配。
  grep “ab*c” readme.file > result
  while( <> )
 {
    if (/ab*c/) {
       print $_;
}
   }
  以上程序片断表示以a开头,后面跟0个以上的b,最后以c结尾。
 
 替代运算符以s字母开头,跟正则表达式,再跟替代的运算符号。
   s/ab*c/def/
  变量是$_会跟正则表达式(ab*c)做比较。进行匹配。
  类型:一个“正则表达式”就是一种类型pattern。分为单字符类型和多字符类型。
单字符类型:单字符类型是最常见和最常用的类型。如a。单字符类型”.”能跟除换行符号(/n)的任何字符匹配。如
/a./
 会和任何长度为二,且开头是a的字符串匹配。除了”a/n”外。
  字符类:(character class),写法是左右两个中括号([]),内放字符。即字符串对应此类型的地方,若出现唯一一个符合括号中列出的字符,就算符合。
  /[abcde]/
 /[aeiouAEIOU]/
若在中括号中放[或者],则需要在前面加反斜杠。如果想表示一段范围,则可以用破折号(dash-)连接。想表示破折号,则前面也必须加反斜杠。
[0123456789]
[0-9]
[0-9/-]
[a-zA-Z]
也可以用“反例”表示字符类别,只要在原来的写法前加上“^”即可。此种类型的意思是任何不在此类别内的单一字符才算上匹配。
[^0-9]
[^aeiouAEIOU]
[^/^]
预定义的字符类别
字符
类别
反例
反例类别
/d
[0-9]
/D
[^0-9]
/w
[a-zA-Z]
/W
[^a-zA-Z]
/s
[/r/t/n/f]
/S
[^/r/t/n/f]
 
[/da-fA-F] # 十六进制数字
类型组合:grouping pattern就是将正则表达式组合起来用。
系列:sequence, 如”abc”
重复符号:multiplier,如星号(*)表示出现零次以上;加号(+)则表示出现一次以上;问号(?)则表示出现零次或一次。
     /fo+ba?r/
以上的类型都是贪婪型的greedy。
$_ = “fred xxxxxxxxx barney”;
s/x+/boom/
一般重复符号:(general multiplier),写法是一对大括号中放一个或两个数字,如/x{5, 10}/,表示x出现5到10次;/x{5,}/表示出现5次以上;/x{5}/表示刚好5个x;/x{0,5}/意思就是”0到5个”
正则表达式如出现两个重复符号,必须遵循“最左边最贪心” (leftmost is greediest) 的规则。
$_ = “a xxx c xxxxxxxxxx c xxx d”;
/a.*c.*d/;
以这个例子,第一个“.”就会和第二个c之前所有的字符符合。可以在重复符号后面加上问号,让它变得“不贪心”(nongreedy)。
$_=”a xxx c xxxxxx c xxx d”;
/a.*c?.*d/
把字符串和正则表达式再该一下:
$_=”a xxx ce xxxxxxx ci xxx d”;
/a.*ce.*d/
这个例子中.*如果匹配到第二个c,则e没有办法匹配。故Perl会重试,降低了效率。实际上只要加个”?”就能让Perl少做很多事。
把括号当记忆空间:另外一个组合符号,是前后包围任何类型的括号对(parentheses pair)。括号不会改变类型匹配的情形,不过可以把匹配的部分记录下来,以后参考。调用记住部分,写法是在反斜线后面加上数字。
   /fred(.)barney/1/;
  会和fredxbarneyx匹配,不会和fredxbarneyy匹配。但是/fred.barney./和两个字符串都匹配。
其中/1代表正则表达式中,第一个用括号括起来的部分。依次有/2, /3…
/a(.)b(.)c/2d/1/;
可以在括号中放入一个以上的字符。如/a(.*)b/1c/;
选项符号:还有一种组合符号称为选项符号(alternation),如“a|b|c”。选项可以不只一个字符,如/song|blue/。
定位类型:anchor pattern定位类型有好几种。定位类型/b,表示目标字符串的这个地方必须是文字边界(word boundary)。所谓“文字边界”就是指符合/w或/W的字符,二个中间的位置;或者界于任何符合/w的字符,与字符串开头(或结尾)中间的位置。
/fred/b/       # 会和 fred 匹配,不会和 Frederick 匹配
//bmo/       # 会和 moe mole 匹配,不会和 Elmo 匹配
//bFred/b/    # 会和 Fred 匹配,但 Frederick alFred 都不匹配
//b/+/b/      # 会和 x+y 匹配,不会和 ++ + 匹配
另一个定位类型/B所在之处就不一定是文字边界,如
//bFred/B/    # 会和 Frederich 匹配,但 Fred Flintstone 不匹配
还有两种类型,代表字符串的开头或结尾的前一个字符。“^”会和字符串的“开头”匹配。^a会匹配以a开头的字符串,不过a^会和”a”和”^”这两个字符串匹配。即”^”失去了特别的意义 。如果想表示字符串开头是有个^号,则用/^即可。另外一个定位类型是”$”,不过表示字符串结尾。c$表示最后出现的字符是c的那个字符串。表示$这个字符,用/$表示。
优先级
名称
表示法
括号(parentheses)
() (?:)
重复运算符(multiplier)
? + * {m, n} ?? +? *? {m, n}?
序列和定位符号(sequence and anchoring)
abc^$/A/Z(?=) (?!)
选项符号(alternation)
|
 
  abc*           # 会和 ab, abc, abcc, abccc, abcccc 匹配
 (abc)*
 ^x|y
 ^(x|y)
 a|bc|d
 (a|b)(c|d)
 (song|blue)bird
=~ 运算符:如果拿来匹配的字符串,不放在$_变量,则可以用”=~”运算符来解决:可把正则表达式放在运算符右侧,左侧则是想比较的字符串。即把正则表达式的默认目标转向运算符的左边运算单元。
$a = “hello world!”;
$a =~ /^he/;
$a=~/(.)/1/;
if($a=~/(,)/1/)
任何能传回标量字符串值的语句,都可以当作=~运算符的左边单元。如,如
print “any last request?”;
if( =~ /^[yY]/) {
print “And just what might that request be”;
print “Sorry, I’m unable to do that./n”
}
忽略大小写:grep有-I这个旗标,意思是忽略大小写;在Perl中提供了类似的方法:在正则表达式第二个斜线之后写上I即可。如/somepattern/i。
   print “any last request?”;
   if ( =~ /^y/i)
   {
   }
指定界限符号:正则表达式前后用斜线包起来,斜线叫分界符号(delimiter),如果想在正则表达式表示斜线这个“字符”,在前面加反斜线。
 $path =
 if($path =~ /^//usr//etc/) {
}
Perl允许设计者自行指定分界符合。可用任何-个非字母、非数字、非空白的字符为分界符号,方法是在第一次使用之前写”m”。
  /^//usr//etc/
 m@^/user/etc@
 m#^/usr/etc#
  内插变量:正则表达式也可以内插变量。
 $what = “bird”
 $sentence = “Every good bird does fly.”;
 if($sentence =~ //b$what/b/)
 {
print “The sentence contains the word $what/n”;
 }
 下面的例子稍微复杂一些:
 $sentence = “Every good bird does fly.”;
 print “What should I look for?”;
 $what = ;
 chomp($what);
 if($sentence =~ /$what/)
 {
print “I saw $what in $sentence./n”;
 }
 else
 {
print “nope... didn’t find it./n”;
 }
特别的只读变量:匹配成功后,名为$1, $2, $3...的这些变量,它们的值被分别设为/1,/2,/3...之值。
   $_ = “this is a test”;
   /(/w+)W+(/w+)/ # 和头两个文字匹配;现在 $1 ”this” $2 ”is”
也可以在列表环境下,一次取得所有匹配的片断。
   $_=”this is a test.”;
 ($first, $second) = /(/w+)W+(/w+)/;
其他预定义的只读变量包括:” $&”,代表字符串中匹配正则表达式的部分;” $`”代表匹配处之前的部分;” $’”代表匹配处之后的部分。
 $_=”this is a sample string.”;
 /sa.*le/;    #和sample匹配。s`是”this is a “,$&是”sample”,$’是”string”
替代运算符:s/old-regex/new-string/这样的用法是最简单的一种替代运算符。如果想让替代运算符在每个匹配的地方取代,而非仅作用在第一个匹配处,在运算符加g.
  $_=”foot fool buffoon”;
 s/foo/bar/g;
替代运算符也可以内插变量,像这样:
  $_=”hello, world”;
 $new = “goodbye”;
 s/hello/$new/;
可以在替代运算符里用字符类型,就不会和固定的字符匹配了:
 $_=”this is a test”;
 s/(/w+) /<$1>/g; #$_现在是   
替代运算符可以加上i,代表忽略大小写,如果已经有g了,则i可以出现在g前后。斜线还可以用其他符号代替。s#fred#barney#;替代运算符也可以用=~改变作用的目标。
split和join函数:正则表达式可以把字符串分成许多字段。split函数可以这样做。而join函数则可以把这些片断组合起来。split函数有两个参数,分别是正则表达式和字符串,它会寻找字符串中匹配正则表达式的部分,其他不匹配的部分会依序用列表值方式传回。
$line= “merlyn::118:10:Randal:/home/merlyn:/urs/bin/perl “;
@fields = split(/:/, $line);
如果要匹配一个以上的:则用:
@fields = split(/:+, $line);
变量$_是split函数的第二个参数的默认值:
$_=”some string”;
@words =split(/ /);
由于参数字符串内没有连续的空白字符,结果会是空字符串。理想的写法是/ +/, //s+/和”一个以上“的空白字符匹配。这是第一个参数的默认值。
@words = split; 用空白字符分割 $_
$line=”merlyn::118:10:Randa;:/home/merlyn:”);
($name,$password,$uid,$gid,$gcos,$home,$shell)=split(/:/,$line);
join函数跟split函数对应,该函数用第一个参数字符串当作”胶”,把第二个参数里面的值一个个“粘“起来。
$bigstring=join($glue,@list);
 

你可能感兴趣的:(脚本语言perl)