没评论
分类: 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$/会匹配fred和fred\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/(?
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
绑定操作符
跟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”
注意join和split第一个参数写法的区别:split第一个参数是模式,join的第一个参数是字符串。
在列表上下文中使用模式匹配时,如果匹配成功,返回的是所有捕获变量的列表;如果失败,返回空列表。示例如下:
my @words = ($text =~ /(a-z)+)/ig);
跨行模式匹配
传统的额正则表达式都是匹配单行文本,用修饰符/m(记忆帮助multiple)可以让它匹配多行文本。示例如下:
open FILE, $filename
or die "Can't open '$filename': $!";
my $lines = join '',
$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)