Chinaunix首页 | 论坛 | 博客
  • 博客访问: 133288
  • 博文数量: 21
  • 博客积分: 576
  • 博客等级: 中士
  • 技术积分: 319
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-23 16:19
个人简介

没评论

文章分类

全部博文(21)

文章存档

2013年(1)

2012年(20)

我的朋友

分类: Python/Ruby

2012-06-19 09:45:08

简易模式匹配

若模式匹配的对象是$_的内容,只要把模式写在//中就可:
$_ = "yabba dabba doo";
if (/abba/) {
    print "It matched!\n";
}
所有双引号内的字符串技巧在模式匹配中同样适用。

m//进行匹配
类似于qw//操作符,m//也可以写成任意其它定界符。如m[],m’’,m..等等。


元字符
点号"."是除了换行符"\n"之外任意单字符的通配符。
反斜线"\"加在任意元字符前使其失去元字符的特殊作用。
圆括号"()"用来模式分组。
竖线"|"表示左边匹配或者右边匹配。

贪婪量词(尽可能多的匹配,不行再吐出)
星号(*)用来匹配前面的内容零次或更多次,也可以写成{0,}
加号(+)用来匹配前面的内容一次或更多次,也可以写成{1,}
问号(?)用来匹配前面的内容零次或一次,也可以写成{0,1}

{x,y}用来匹配前面的内容x次到y次,{x,}表示x次及以上,{x}表示x次。注意不能省略第一个数字,如不能用{,y}表示y次及以下。
非贪婪量词(尽可能少的匹配,不行再吞下一个字符)

每个贪婪量词都有对应的非贪婪量词,以上四个分别对应的是:*?+???{x,y}?


模式分组
圆括号除了模式分组外,还可以让圆括号中匹配的文字可以被重新引用。\1\2这样的写法就是在使用反向引用,数字代表着圆括号(左括号)出现的顺序。perl 5.10版本引入了一种新的写法\g{N},其中N代表组号,如果是负数则表示从右往左算。

字符集是指一串可能出现的字符集合,通过写在方括号"[]"内来表示。它只匹配单个字符,但可以是字符集里列出的任意一个。可以用连字符"-"来表示从前 者到后者的字符集,如[a-z]表示全部小写英文字母。可以用脱字符"^"表示已经列出的字符以外的字符集,如[^def]表示除了这3个字符外的其它任 意字符。
字符集简写
可以用简写来表示一些常用的字符集:
\d
表示任意数字字符集[0-9]
\w
表示单词字符[A-Za-z0-9_]
\s
表示空白字符集[\f\t\n\r ],它等于包含5种空白的字符集:换页、制表、换行、回车以及空格。
perl 5.10
版本后增加了更多字符集来描述空白。\h匹配横向空白[\t ]\v匹配纵向空白[\f\n\r]\R匹配任何类型的断行。

反义简写
\D
表示[^\d]
\W
表示[^\w]
\S
表示[^\s]

可选修饰符用于正则表达式结尾的定界符的右边,来改变其默认行为。

/i表示不区分大小写

/s表示点号(.)匹配任意字符(点号默认不匹配空格)

/x表示忽略模式里面的空白

 

锚位

脱字符(^)用来标示字符串的开头。(注意区分脱字符在字符集中的含义)

美元符号($)用来标示字符串的结尾。(细节注意:/^fred$/会匹配fredfred\n这两个字符串,即不管字符串结尾有没有换行符,都可以匹配)

 

单词锚位

\b是单词(\w)边界锚位,它匹配任何单词的首尾。

\B是非单词边界锚位,跟\b的含义相反。

 

绑定操作符

默认情况下模式匹配对象是$_,绑定操作符=~能让perl拿右边的模式来匹配左边的字符串,而不是$_

 

模式串中的内插:正则表达式可以进行双引号形势的变量内插。

 

捕获变量

类似模式分组反向引用,$1表示第一个圆括号,$2表示第二个圆括号。与模式分组反向引用的区别在于:反向引用用在模式串中,变量捕获用在模式串匹配完成之后。

捕获变量的生命周期到下次成功的模式匹配为止。

不捕获变量

?:可以表示圆括号不捕获变量,而只是用来分组。用法示例:

If (/(?:bronto)?(steak|burger)/)   #不捕获bronto

问号用法总结:原文问号(需转义)、有无量词、非贪婪修饰符和不捕捉前缀。

命名捕获

Perl5.10引入了命名捕获的概念,让捕获的结果进入一个特殊的哈希%+。示例如下:

use 5.010;

my $names = 'Fred or Barney';

if ( $names =~ m/(?\w+) (?:and|or) (?\w+)/ ) {

    say "I saw $+{name1} and $+{name2}";

}
%+{name1}引用第一个括号中匹配的值。同样的,可以用\g{name1}来进行反向引用。

 

自动匹配变量

$`表示字符串匹配前的部分

$&表示字符串匹配的部分

$’ 表示字符串匹配后的部分

三个部分合起来就是原先的字符串。值得注意的是这3个变量的使用可能会影响程序运行的效率。

优先级

正则表达式中的优先级从高到低如下:

Regular expression feature                   Example

Parentheses (grouping or capturing)            (…), (?:…), (?

Quantifiers                                a*, a+, a?, a{n,m}

Anchors and sequence                       abc, ^, $, \A, \b, \z, \Z

Alternation                                a|b|c

Atoms                                    a, [abc], \d, \1, \g{2}

在复杂的情况下,或者不是很清楚优先级的时候,可以用括号来避免出错。

 

s///记忆帮助:substitute)把指定变量合乎模式的部分替换为另外的内容。示例如下:

s/you/me/;  #you替换成me

s/(\w+)(\w+)/$2,$1/; #括号内匹配内容互换

s/(\+w)//; #括号内匹配内容替换为空

更多示例参见原书p.147

s///返回的是布尔值,替换成功时为真,否则为假。

 

默认情况下s///只进行一次替换,修饰符/g可以让它进行全局替换。其它模式匹配中使用的/i/x/s修饰符在这里功能相同。

s///也可以改变定界符,如果是一般没有左右之分的字符,直接使用即可,如s###。如果是成对字符,就必须使用两对,一对圈引模式,一对圈引替换字符串。如s{me},s%you%(me)

 

绑定操作符

m//一样,可以用绑定操作符为s///选择不同的目标。

大小写转换

\U可以把其后的所有字符转换成大写(uppercase

\L可以把其后的所有字符转换成小写(lowercase

\u可以把其后的第一个字符转换成大写(uppercase

\l可以把其后的第一个字符转换成小写(lowercase

上述转义字符可以组合使用,并且先后次序可以任意,如\u\L表示首字母大写其余小写,。

\E可以用来结束上面的大小写替换,如:

s/(me) with (you)/\U$2\E with $1/i;  # $_ is now "YOU with me."

 

split操作符可以根据分隔符拆开一个字符串。用法如下:

@fields = split /separator/,$string;

@fields = split /:/,”abc:def:g:h”; #得到@fields(“abc”,”def”,”g”,”h”)

如果两个分隔符连在一起,就会产生空字段。但是它会自动把结尾的空字段省略掉。如果要保留这些空字段,则要用到split的第三个参数-l。如:

@fields = split /:/,”::a:b:c::d::::”  #得到@field(“”,””,”a”,”b”,”c”,””,”d”)

可以用/\s+/模式进行空白分割,在此模式下所有的空白被当成一个分隔符处理,并且会省略开头的空白。

split默认以空白字符分割$_: my @fields = split; #等效于split /\s+/,$_;

 

join函数可以把几个片段组合成一个字符串。用法如下:

my $result = join $glue,@pieces; #$glue相当于胶水,把@pieces中各个部分胶成一个

my $x = join “:”,4,6,8,10,12;  #$x”4:6:8:10,12”

注意joinsplit第一个参数写法的区别:split第一个参数是模式,join的第一个参数是字符串。

 

在列表上下文中使用模式匹配时,如果匹配成功,返回的是所有捕获变量的列表;如果失败,返回空列表。示例如下:

my @words = ($text =~ /(a-z)+)/ig);

 

跨行模式匹配

传统的额正则表达式都是匹配单行文本,用修饰符/m记忆帮助multiple)可以让它匹配多行文本。示例如下:

open FILE, $filename

    or die "Can't open '$filename': $!";

my $lines = join '', ;   #$filename读到一个变量里

$lines =~ s/^/$filename: /gm;  #$filename里每行开头加上文件名:

 

变量$^I

$^I = “.bak”;   #把要修改的文件创建以.bak为后缀的备份文件

注意$^I设为空时,不会留下任何备份。

 

在命令行进行在线编辑

$perl –p –i.bak –w –e ‘s/randall/randal/g’ fred*.dat

-p选项可以让perl自动生成一小段程序,类似于:

while (<>){

print;

}

-i.bak就是把$^I设为.bak。如果不想做备份,直接写-i即可。

-e表示后面跟的是程序代码。

fred*.dat表示@ARGV值匹配此文件模式的所有文件名。

推荐扩展阅读:Mastering Regular Expressions by Jeffrey Friedl (O’Reilly)

阅读(1306) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~