blue1025的个人空间 https://blog.eetop.cn/mj8051 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

第9章 用正则表达式处理文本

已有 1612 次阅读| 2008-9-27 14:25 |个人分类:PERL

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)之一。


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 13

    粉丝
  • 14

    好友
  • 15

    获赞
  • 23

    评论
  • 2819

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-3-29 14:21 , Processed in 0.013990 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部