我认为正则是任何脚本语言的 重点,perl也是必须的,不过基本规则是一致。
1. 正则表达式
默认是对$_ 进行匹配,如下:
$_ = “I dream a millinon”;
if(m/eam/)
{
print “match success!” ;
}
可以通过=~进行绑定,符号成为绑定符,优先级非常高
my $word = “let me become a million”;
if( $word =~ m/^let/)
{
print “match success!”
}
普配模式可以被变量替换。
my $model = “[a-z]+_[0-9]+/.log”;
my @hash_c ;
while(<STDIN>)
{
if(m/$model/i)
{
$hash_c{“$_”} = “1”;
}
}
1.1.元字符
. 单个字符,不包括 \n
/ 转义
* 前面的字符重复0或多次
? 前面的字符重现0或一次
+ 前面的字符重复1或多次
() 分组,扩成整体
| or
[] 内部中的一个字符
\d 0-9中的一个
\w 任意一个字母、数字、下划线
\s 一个空格
^ 非 [^\d] 非数字 [^\w] 非字符
{n,m} 前一个对象重复的次数
1.2.修饰符
修饰符放在m//匹配的后面,m//匹配可以为任何对应符号。
/i 大小写无关 if(/yes/i) {#大小写无关
/s 使用时.可以匹配任何字符 if(/Barney.*Fred/s)
/x 允许你在模式中加入任何数量的空白
/g 全局的
/m 允许换行匹配
说明三个修饰符可以组合使用
if (m{barney.*red}six)
{
print “That string mentions Fred after Barney!\n”;
}
#修饰符包括包括/s, /i, /x
#可以包含任何字符
1.3.位置符
perl里专业词为锚定,anchoring
^ 开始 /^fred/
$ 结尾 /rock$/
\b 词界
1.4.匹配变量
在模式中使用括号,匹配到的字符串中与括号对应的部分可以被取出来。
my $dino = "I fear that I'll be extinct after 1000 years.";
if ($dino =~ /(\d*) years/) {
print "That said '$1' years.\n"; # 1000
}
输出为:That said '1000' years.
这些匹配变量的值会保持不变,直到下一个模式成功匹配为止,所以如果使用这些内存值,必须良好的保存:
if($wilma =~ /(\w+)/){
my $wilma_word = $1;
…
}
三个内置匹配变量:
$` 匹配字符串之前的部分
$& 匹配的字符串
$’ 匹配字符串之后的部分
如果你使用了这三个自动匹配变量中的任意一个,无论在程序的什么地方,其它地方的正则表达式的运行数度会变慢一些,尽量不使用。
1.5.优先级
优先级从高到低分别为:
()
数量词
锚定和序列
|
1.6.处理文件
1.6.1. 使用s///进行替换
m// 这个模式匹配看作同文字处理器的“查询(search)”类似的功能
s ///操作的则类似于“查询并替换(search and replace)”
实例 :
#! /usr/bin/perl use strict ; use warnings ; #匹配 my $dino = "I fear that I'll be extinct after 1000 years."; if ($dino =~ /(\d*) years/) { print "That said '$1' years.\n"; # 1000 } #默认下的模式替换 $_ = $dino ; s/(\d*) years/ 25 minutes/; print $_ ,"\n"; # $dino =~ s/(\s\d*\syears)/\U$1-five days/; print $dino,"\n";
|
结果: 1. 修饰符/U 将字符全部转换为大写 2. $1即匹配变量 3. |
如同m//和qw//一样,我们也可以改变s///的分隔符。但这里使用了3个分隔符:
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;
1.6.2. split操作
开头的空元素会被返回,但结尾的空元素被丢弃
@fields = split /:/,“abc:def::g:h”;
my $some_input = “This is a \t test.\n”;
my @args = split /\s+/, $some_input; #(“This”, “is”, “a”, “test.”)
1.6.3. join函数
join 函数不使用模式,但它完成同split 相反的操作
join 的第一个参数是字符串,而非模式
如果列表中元素个数小于2,则不会有粘合的元
my $x = join“:”, 4, 6, 8, 10, 12; #$x 为“4:6:8:10:12”
my $y = join “foo”, “bar”; #得到“bar”
my @empty; #空数组
my $empty = join “baz”, @empty; #没有元素,因此为空串
1.6.4. 列表存储分割值
使用列表或者hash结构存储分割值
#! /usr/bin/perl use strict ; use warnings ; my $text = "Fred dropped a 5 ton granite block on Mr. Slate"; my @words = ($text =~ /([a-z]+)/ig); print "Result: @words\n";
my $data = "Barney Rubble Fred FlintstoneWilma Flintstone"; my %last_name = ($data =~ /(\w+)\S+(\w+)/g); while((my $key,my $value) = each %last_name) { print "$key=>$value\n" ; } |
结果: 说明:
|
1.7.更强大的正则表达式
1.7.1. 贪婪和非贪婪
贪婪模式:
在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"{m,n}", "{m,}", "?", "*", "+",具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。
比如,针对文本 "dxxxdxxxd",举例如下:
表达式 | 匹配结果 |
"\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd" | |
"\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d" |
由此可见,"\w+" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "d",但那也是为了让整个表达式能够匹配成功。同理,带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配,带 "?" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这种匹配原则就叫作 "贪婪" 模式。
非贪婪模式:
在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。
举例如下,针对文本 "dxxxdxxxd" 举例:
表达式 | 匹配结果 |
"\w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"\w+?" 只匹配了一个 "x" | |
为了让整个表达式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"\w+?" 匹配 "xxx" |
匹配过程:
贪婪模式,匹配到最大,逐步回撤
非贪婪模式,匹配到最小逐步放大
1.7.2. 更新文件
关键是 特殊变量$^I
看一个例子:
#! /usr/bin/perl -w use strict; chomp(my $date = `date`); $^I =".bak";
while(<>) { s/^Author:.*/Author: Randal L. Scharwartz/; s/^Phone:.*\n//; s/^Date:.*/Date: $date/; print; } |
运行: 产生文件data.txt.bak |
说明: 内容被写入到新文件,新文件是源文件加一个后缀,后缀即为$^I存放的值 如果没有这个变量,那内容将被输出到STDOUT
|
如果操作很多个文件的时候,将是非常简单。
这个也可以在命令行实现:
$perl –p –i.bak –w –e ‘s/Randall/Randal/g’fred*.dat