1. 使用正则表达式处理文件
1.1 使用s///进行替换
$_ =“He’s out bowling with Barney tonight.”;
s/Barney/Fred/; #Barney 被Fred 替换掉
print “$_/n”
s/with (/w+)/agaist $1’s team/;
print “$_/n”; #为“He’s out bowling against Fred’s team tonight”;
$_ =“green scaly dinosaur”;
s/(/w+) (/w+)/$2, $1/; #现在为“scaly, green dinosaur”;
s/^/huge, /; #现在为“huge, scaly, green dinosaur”
s/,.*een//; #空替换,现在为“huge dinosaur”
s/green/red/; #匹配失败,仍然为“huge dinosaur”
s//w+$/($`!)$& /; #现在为“huge (huge !)dinosaur”
s///s+(!/W+)/$1 /; #现在为“huge (huge!) dinosaur”
s/huge/gigantic/; #现在为“gigantic (huge!) dinosaur”
s///会返回一个Boolean 值。如果成功替换则返回true;否则返回false:
1.1.1.使用/g 进行全局替换
$_ = “home, sweet home!”;
s/home/cave/g;
print “$_/n”; # “cave, sweet cave!”;
$_ =“Input data/t may have extra whitespace.”;
s//s+/ /g; #现在是“Input data may have extra whitespace.”
s/^/s+//; #将开头的空白去掉
s//s+$//; #将结尾的空白去掉
1.1.2.不同的分隔符
s#^https://#http://#;
如果使用的是配对的字符,也就是说其左字符和右字符不的,则必需使用两对:一对存放模式,一对存放替换的字符串。
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;
1.1.3.可选的修饰符
s#wilma#Wilma#gi; #将所有的WilmA,或者WILMA 等等,由Wilma 替换掉
s{_ _END_ _.*}{ }s; #将END 标记及其后面的行去掉,记住/i /s /x /g
1.1.4.绑定操作
$file_name =~ s#^#/##s; #将$file_name最前面加#号。注意每个#的含义
1.1.5.大小写转换
$_ =“I saw Barney with Fred.”;
s/(fred|barney)//U$1/gi; #$_现在是“I saw BARNEY with FRED.”
s/(fred)|barney//L$1/gi; #$_现在是“I saw barney with fred.”
s/(/w+) with (/w+)//U$2/E with $1/I; #$1 现在是“I saw FRED with barney.”
s/ (fred|barney)//u$1/ig; #$_现在是“I saw FRED with Barney.”
也可以同时使用它们。如使用/u 和/L 表示“第一个字母大写,其它字母均小写”◆:◆/L 和/u 可以按任意顺序出现。Larry 意识到人们有时可能按相反顺序使用它们,因此他将Perl 设计成,在这两种情况下都是将第一个字
母大写,其余的小写。Larry 是个非常好的人。
s/(fred|barney)//u/L$1/ig; #$_现在为“I saw Fred with Barney.”
这些在替换中出现的大小写转换的修饰符,也可在双引号中使用:
print “Hello, /L/u$name/E, would you like to play a game?/n”
1.2 split 操作
@fields = split /:/, “abc:def:g:h”; #返回(“abc”, “def”, “g”, “h”)
@fields = split /:/,“abc:def::g:h”; #得到(“abc”, “def”, “”, “g”, “h”)
这里有一条规则:开头的空元素会被返回,但结尾的空元素被丢弃
@fields = split /:/, “:::a:b:c:::”; #得到(“”, “”, “”, “a”, “b”, “c”);
my $some_input = “This is a /t test./n”;
my @args = split //s+/, $some_input; #(“This”, “is”, “a”, “test.”)
默认时,split 对$_操作,模式为空白:
my @fields = split; #同split //s+/, $_;
1.3 join 函数
my $x = join“:”, 4, 6, 8, 10, 12; #$x 为“4:6:8:10:12”
my @values = split /:/, $x; #@values 为(4, 6, 8, 10, 12)
my $z =join “-”, @values; #$z 为“4-6-8-10-12”
1.4 列表上下文中的m//
返回的是$1 $2 $3…
my $text = “Fred dropped a 5 ton granite block on Mr. Slate”;
my @words = ($text =~ /([a-z]+)/ig);
print “Result: @words/n”;
#Result: Fred dropped a ton granite block on Mr slate
my $data = “Barney Rubble Fred FlintstoneWilma Flintstone”;
my %last_name = ($data =~ / (/w+)/S+(/w+)/g);
每当模式匹配成功时,将返回一对值。这些一对一对的值就成了hash 中的key/value 对。
1.5 更强大的正则表达式
1.5.1.非贪婪的数量词
fred and barney went bowling last night barney 上使用/fred.+barney/进行匹配
如果真如书上说,用回退的方式匹配,则匹配的应该是整个句子了,做个实验!!实验表明的确是这样
现在我们来看看模式为/fred.+?barney/时的过程
将贪婪改成了非贪婪,应该匹配的是前面部分,binggo!
要删掉body标记:
I thought you said Fred and <BOLD>Velma</BOLD>, not <BOLD>Wilma</BOLD>
$#<BOLD>(.*?)</BOLD>#$1#g; #正确,改成了非贪婪,匹配最先发现的</BOLD>
如果没有?贪婪的话就留下了中间两个
花括号的非贪婪类型看起来一样,只是在闭花括号后有一个问号,如{5,10}?或者{8,}?◆。甚至问号数量词也有非贪婪类型:??。它匹配一次或者0 次,但倾向于匹配0 次。
1.5.2.匹配多行文本
$_ =“I’am much better/nthan Barney is/nat bowling,/nWilma,/n”;
print “Found ‘wilma’at start of line/n”if /^wilma/b/im;
锚定^和$是指整个字符串的开头和结束(参阅第八章)。但/m 这个正则表达式选项允许它们根据内部的换行符进行匹配(将m看作多行(think m for multiple lines))。这时锚定针对每一行,而非整个字符串。因此,这个模式可以匹配上
将文件名字加在每一行的开头处:
open FILE, $filename
or die “Can’t open ‘$filename’: $!”;
my $lines = join '', <FILE>;
$lines =~ s/^/$filename: /gm;
1.5.3.更新大量文件
#! /usr/bin/perl –w
use strict;
chomp(my $date = ‘date’);
$^I =“.bak”; #如果没有它,<>得到的$_在被改变时是不会改变原输入文件的,但是有了它就会改变,同时生成以“.bak”为后缀名的备份文件备份原来的文件,若它的值是空串,则不会产生备份文件,而直接改变原文件的内容
while(<>){
s/^Author:.*/Author: Randal L. Scharwartz/;
s/^Phone:.*/n//;
s/^Date:.*/Date: $date/;
print;
}
这个例子好有用,要实验好好探讨
1.5.4.在命令行中进行修改
$perl –p –i.bak –w –e ‘s/Randall/Randal/g’fred*.dat
意思就是执行批量替换,原来的放在.bak的备份文件里,也可以
perl -pi -e "s/oldstring/newstring/g"
这样就不备份
1.5.5. 非捕捉用的括号
if(/(bronto)?saurus (steak|burger)/) #我不想bronto存在$1里,但是此时又不能不加括号,怎么办?
{
print “Fred wants a $2/n”;
}
和下面的区别
if(/(?:bronto)?saurus (steak|burger)/) #这样就把括号改成了非捕捉用的了,自然bronto就不会存在$1里
{
print “Fred wants a $1/n”;
}