ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Perl 小骆驼 9章笔记 使用正则表达式处理文件 (小骆驼第五版)

Perl 小骆驼 9章笔记 使用正则表达式处理文件 (小骆驼第五版)

原创 Linux操作系统 作者:zhaojienju 时间:2011-03-11 17:52:51 0 删除 编辑

第九章 使用正则表达式处理文件

替换s///
$_="with Barney";
s/Barney/Fred/; 将Barney替换成Fred
如果没有匹配,则什么都不做.

例子:
s/(\w+)(\w+)/$2,$1/;  交换了前两个,加上一个逗号
s/^/huge,/; 头加上huge,
如果s///成功,返回true,否则返回false。

s///只进行一次替换,要全局匹配使用g
s/home/cave/g;

s/\s+/ /g; 将多个空格替换成单个空格
s/^\s+//; 去掉开头空白
s/\s+$//; 去掉结尾空白

s也可以和其他符合一起使用,如s#hello#world#;
还可以使用配对字符:
s[hello](world);

除了/g,还可以使用/i, /x, /s。

绑定操作符=~
$filename =~  s/hello/world/;

-----------------------------------------------------------------

\U转义字符会将其之后的字符都转换成大写。\L,小写。
结束大小写转换的影响用\E.
\u, \l只影响之后的第一个字符。

例子:
$_="I saw barney with fred.\n";
s/(\w+) with (\w+)/$2 with $1/;     
print;                              I saw fred with barney.

$_="I saw barney with fred.\n";
s/(\w+) with (\w+)/\U$2 with $1/;
print;                              I saw FRED WITH BARNEY.

$_="I saw barney with fred.\n";
s/(\w+) with (\w+)/\U$2\E with $1/;
print;                    I saw FRED with barney.

$_="I saw barney with fred.\n";
s/(\w+) with (\w+)/\u$2 with \u$1/;
print;                    I saw Fred with Barney.

$_="I saw barney with fred.\n";
s/(\w+) with (\w+)/\L\u$2 with \u$1/;
print;                    I saw Fred with barney.
这个例子可以看到第一个\u起作用了,但第二个\u没有起作用。

-----------------------------------------------------------------
split操作符:根据分隔符拆开一个字符串
@fields=split /separator/, $string;

split会保留开头处的空字段,并省略结尾处的空字段。
@fields = split /:/, ":::a:b:c:::";
这个会得到"","","","a","b","c"

利用/\s+/模式进行空白分割也很常见,所有空白会被当作一个空格来处理。

split默认会议空白字符分隔$_。

-----------------------------------------------------------------
join函数:和split相反,把片段联合成一个字符串。
my $result = join $glue, @pieces;
例如:
my $x = join ":", 4, 6, 8;
print "$x";                4:6:8
列表中至少有两个元素,否则无法成功。

-----------------------------------------------------------------
使用split时,我们指定分隔符。也可以换个角度,直接匹配真正有用的数据字段。
例如:
my $text = "Fred dropped a 5 ton granite block on Mr. Slate";
my @words = ($text =~ /[a-z]+/ig);   #匹配所有字母a-z
print "Result: @words\n"; #打印Result: Fred dropped a ton granite block on Mr. Slate

该例子可以将一个字符串变成哈希:
my $data = "Barney Rubble Fred Flintstone Wilma Flintstone";
my %last_name = ($data =~ /(\w+)\s+(\w+)/g);


----------------------------------------
更强大的正则表达式

贪婪量词 * + ? {}
会在保证整体匹配的前提下,尽可能多的匹配字符串。

贪婪量词对应一个非贪婪量词,匹配的字符串越短越好。 *?  +? ??  {}?
使用贪婪还是非贪婪,哪种效率更高,取决于正则表达式处理的数据。

这个例子说明了贪婪量词和非贪婪量词在某些情况下匹配的字符不同.
$_="Test xml namebirth";
s#(.*)#$1#g;
print "$1\n";                    namebirth   

$_="Test xml
namebirth";
s#(.*?)#$1#g;
print "$1\n";                    birth

----------------------------------------
跨行的模式匹配,在模式后加上/m:
$_ = "I'm much better\n than Betty is \nat bowling,\nWilma.\n";
if (/^Wilma/m) {
  print "$1\n";
}
测试了一下,在active perl上不work.....

----------------------------------------
一次更新多个文件
使用$^I变量

例子:
chomp(my $date, `date`);
$^I=".bak";

while (<>) { #此时就会读入所有文件,重命名为.bak文件,打开新文件,输出所作替换。
  s/^Author:.*/Author:Alice Zhao/;
  s/^Date:.*/Date: $date/;
  s/^Phone:.*\n//;
}

----------------------------------------
从命令行进行在线编辑
比如将上百个文件中的Randal1改成Randal
perl -p -i.bak -w -e 's/Randal1/Randal/g' fred*.dat
其中-p选项让perl自动生成一小段程序,类似
while (<>) {
  print;
}
-i.bak把$^I设成.bak
-e表示后面紧跟的是程序代码,这段代码会被放到循环中print前。
最后一个命令行参数为fred*.dat,表示@ARGV的值是匹配此文件名模式的所有文件名。

相当于该程序:
#!/usr/bin/perl -w
$^I = ".bak";

while (<>) {
  s/Randal1/Randal/g;
  print;
}

------------------------------------------
习题
1. 模式是($what){3}
my $what = 'fred|barney';
$_="fredbarneybarney";

/($what){3}/;
print $&;


2.
$filename = $ARGV[0];

$filename =~ s#\.(\S)*#\.out#;

print "$filename\n";

open OUT, ">$filename";

while (<>) {
  s/larry/fred/gi;   
  print OUT $_;
}

3.
#!c:\perl\bin\perl -w

$filename = $ARGV[0];

$filename =~ s#\.(\S)*#\.out#;

print "$filename\n";

open OUT, ">$filename";

while (<>) {
  chomp;
  s/fred/\n/gi;
  s/wilma/fred/gi;
  s/\n/wilma/gi;   
  print OUT $_;
}


4.

 $^I=".bak";

while (<>) {
  s/(^#!.*$)/$1\n##Copyrigh (C) 2011 by Alice Zhao\n/;
  print;
}

后面答案也可以:
 while (<>) {
  if (/^#!/) {
    $_.="##Copyrigh (C) 2011 by Alice Zhao\n/;
  }
  print;
}

5.
参考书后答案。思路就是先得到文件名列表,读入,将已有copyright的文件名移除。
然后重置@ARGV,重新读入文件信息,加上copyright。
#!c:\perl\bin\perl -w

my %hash;
foreach (@ARGV) {
  $hash{$_}=1;
}

while (<>) {
  if (/^##Copyrigh/) {
    delete $hash{$ARGV};
  }
}

@ARGV= sort keys %hash;
$^I = ".bak";
while (<>) {
  if (/^#!/) {
    $_.="## Copyright (c) 2011 by Alice Zhao\n";
  }
  print;
}






来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/11903161/viewspace-689226/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-10-05

  • 博文量
    80
  • 访问量
    192306