SOURCE HTML: http://socvista.com/bbs/redirect.php?fid=71&tid=926&goto=nextnewset
10:11 用s///来替换文本
== 基本常识
s///默认是对$_进行处理。
s/kobe/fan/; # 将kobe替换成fan
如果替换成功则变量被修改,否则变量保持不变。
如果替换成功返回true,否则返回false,利用这个返回值可以做一些控制。
if (s/kobe/fan/) {};
== 全局替换 /g
如果没有这个全局声明,则替换只在字符串中发生一次,忽略剩余。
如果施加了这个option则整个字符串符合条件的全部被替换。使用方法:
s/kobe/fan/g
== 不同的替换符号
和 m// 一样,替换符号可以自己定义。
比如:
s#kobe#fan#g
但是如果是成对的符号必须成对使用。例如
s{kobe}(fan)
s{kobe}#fan#;
== option 修改符
和m//一样,可以使用 /s /i /x 等修正符号。
== binding 符号
和m//一样,可以使用 =~ 符号来进行binding。念作:替换。
$file_name =~ s/kobe/fan/;
== 大小写转换
一个用途就是找到某些字符,然后全部转换成大写或者小写。
大写用 \U 小写用 \L。他们将替换所有符号条件的字符。
s/(kobe)/\U$1/gi; # 将不区分大小写的kobe全都转换成KOBE大写
s/(kobe)/\L$1/gi; # 将不区分大小写的kobe全都转换成kobe小写
如果用\u \l ,则只替换第一个。
还有一些复杂的组合应用。可能用不着,我都记不住,所以不再赘述。
13:08 分割文本
== split 操作符
语法:
@fields = split /separator/, $string;
看例子就都明白了。
@fields = split /:/, "abc:def:g:h"; # 返回一个List,("abc", "def", "g", "h")
@fields = split /:/, "abc:def::g:h"; # 返回一个List,("abc", "def", "", "g", "h") 注意中间有一个空的域
默认的情况是对$_变量用whitespace来分割,然后返回一个list。
my @fields = split;
13:17 组合文本
== join 函数
语法:
my $result = join $glue, @pieces;
看例子,
my $x = join ":", 4, 6, 8, 10, 12; # 返回值就是“4:6:8:10:12”
my $z = join "-", @values;
13:44 non-greedy quantifier
== 快速匹配的quantifier
常用的quntifier 有?+*等几种。但是在匹配的时候,他们都倾向于匹配更多的内容,导致额外的处理时间增加。non-greedy
quantifier则刚好相反,其目的就是匹配尽量短的结果,这样就大大节省了处理时间。其方法非常简单,就是增加一个?号。比如
.+ ==> .+?
.* ==> .*?
{5,10} ==> {5,10}?
{8,} ==> {8,}?
13:59 匹配并处理多行文本
== /m的威力
在匹配的时候提到过option选项。/m就是其中一个,可以记忆为“multiple lines”,表示内含多个行(用\n分割),每个行都要同样处理。例子
open FILE, $filename
or die "cannot open '$filename' : $!";
my $text = join '', <FILE>; # 连接符是empty
$text =~ s/^/$filename: /gm;
print $text;
上面例子的结果是在每一行上都加了文件名。
14:40 同时更新多个文件
== 用<>符号处理多个文件
来看一个例子。
#!/usr/bin/perl -w
chomp(my $date = localtime);
$^I = ".bak";
# 为待处理的文件创建同名备份文件,扩展名为bak
while (<>) {
# <>符号会将所有涉及到的多个文件内容读入,然后逐行处理
s/^Author:.*/Author: Kobe/;
s/^Phone:.*//;
s/^Date:.*/Date: $date/;
Print;
# 回写修改后的内容
}
<>符号会先将源文件改名为*.bak,同时创建一个新的文件(和源文件同名),然后从bak中读取内容,处理后写回到新文件中。
这里的<>是连接一个文件输入块的行输入符,所谓的文件块可以是若干个文件的联合输入,这些文件通过perl脚本的参数来指定。比如:
./my_program fred barney betty
这个脚本在执行时有三个文件参数,因此这三个相关文件将被读取并连接在一起,然后通过<>符合一行一行读入。直到最后一个文件的EOF处,才会返回一个undef值,表示文件结束
14:58 Non-capturing parentheses
== 如何使用括号而不保存变量
方法是使用?:说明符号。比如
if ( /(?:kobe)? want (steak|burger)/ ) {
print "Kobe want a $1\n";
}
这里的(kobe)中加入了?:表明这个括号只是为了grouping,不需要为其保存变量。
所以$1指的是后面匹配到的(steak|burger)之一。