找回密码
 注册
查看: 12362|回复: 3

利用perl语言正则表达式更新大量文件

[复制链接]
发表于 2011-11-14 20:56:45 | 显示全部楼层 |阅读模式
更新文件最常用的方法是写一个和以前的文件相似的新文件,我们可以根据的需要进行修改。如你所知,这和对同一个文
件上进行更新的结果类似,但上述方法有一些副作用。
本例中,我们有相似格式的上百个文件。其中一个是fred03.dat,如下:
Promram name: granite
Author: Gilbert Bates
Company: RockSoft
Department: R&D
Phone: +1 503 555-0095
Date: Tues March 9, 2004
Version: 2.1
Size: 21k
Status: Final beta
我们希望修改这个文件,使之含有不同的信息。下面是我们希望修改后它所呈现的样式:
Program name: granite
Author: Randal L. Schwartz
Company: RockSoft
Department: R&D
Date: June 12, 2008 6:38 pm
Version: 2.1
Size: 21k
Status: Final beta
简言之,我们需要在3 个地方进行修改。作者(Author)的名字需要更改,日期(Date)需要更新,电话(Phone)需要删除。
我们需要在上百个这样的文件中作这些修改。
Perl 可以通过尖括号操作符(<>)对文件进行修改。下面程序能完成我们希望的工作,虽然第一次看时,不是很明显。这个
程序只有一个新的特性:特殊变量$^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;
}
由于需要当前的日期,因此在程序开端使用了系统命令:date。另一种获得时间的更好的方法是(格式有些不同)使用Perl
自带的localtime 函数,其在标量context 中使用:
my $date = localtime;
下一行是给$^I 赋值,我们现在不讨论它。
根据我们现在所知的,上述操作的结果是文件中新修改的部分被输出到终端,内容快速滚动,但文件本身不会被修改。
由尖括号操作(<>)所得到的文件列表来源于命令行。主循环读入,更新,输出每一行。(根据我们现在所知的,上述操作
的结果是文件中被修改的部分被输出到终端,这些内容快速滚动,但文件本身不会被修改。)第二个替换操作将含有电话
(phone)号码的整行由空串替换,连换行符一起替换掉。这行输出时,什么也不会出现,就像电话(Phone)号码从没存在过一
样。还有大量的行不会被这三个模式所匹配,他们在输出时不会有任何更改。
结果接近于我们所期望的了,除了还不知道怎样将更新的信息写回文件。答案是变量$^I。默认时为undef,此时没有什么
特殊的地方。但给它设置某些串时,它使尖括号操作(<>)变得有些特殊。
我们知道尖括号(<>)的神奇特点:如果没有指定文件名,则其从标准输入流中自动打开和关闭一系列文件进行读入。但如
果$^I 中有字符串,这个字符串则会成为备份文件的扩展名。我们在下面仔细讨论。
我们假设此时尖括号(<>)打开的文件是fred03.dat。它像以前那样打开它,但进行了重名名,把它叫做fred03.dat.bak◆。这
很好,因为不在使用之前的名字。现在<>将这个新的文件作为默认的输出,因此任何内容将输出到那个文件中◆。while
循环会从旧的文件中读入一行,更新它,再把它输出到新文件中。在一台普通的机器上运行这个程序,几秒钟就能更新上
百个文件。非常强大,不是吗?
◆过程的细节之处,在不同的non-Unix 可能有所不同;但结果几乎是一样的。阅读移植到你的系统中Perl 的发布须知(release notes)。
◆<>尽量继承以前文件的权限和所有者等设置;例如,如果以前的文件是全局可读的(world-readable),则新文件也应当是全局可读的。
当程序结束时,用户能见到什么?用户说,“啊,我看到了发生的改变。Perl 修改我的文件fred03.dat,做了我希望的修改,
并将早期的文件保存在叫做fred03.dat.bak 的文件之中”但我们知道的真相是:Perl 不会修改任何文件。它新建了一份修改
后的拷贝,说“Abracadabra(咒语)”,当在魔术棒出现过闪光后,文件就被交换了。很狡猾吧!
某些人喜欢将~ (tilde)作为$^I 的值,这同emacs(Unix 上的一个编辑器)处理备份文件类似。$^I 另一个可能值是空串,
这会修改文件,但不会将原来的文件进行备份。由于在模式中少输入几个字符就能将以前的数据去掉,因此除非有特殊的
理由,否则不要使用空串。毕竟当这一切完成时,再删除备份文件也是很容易的。如果什么地方出了问题,可以将备份文
件命名成以前的文件,知道如何使用Perl,你将非常轻松
回复

使用道具 举报

发表于 2012-5-16 15:41:34 | 显示全部楼层
我们假设此时尖括号(<>)打开的文件是fred03.dat。它像以前那样打开它,但进行了重名名,把它叫做fred03.dat.bak◆。

还是没太看懂这个文件是如何打开的?能说的再详细一点吗?
回复 支持 反对

使用道具 举报

发表于 2015-8-14 17:35:38 | 显示全部楼层
很好,学写了。刚好要用到这类代码。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|生物统计家园 网站价格

GMT+8, 2025-1-22 19:33 , Processed in 0.023448 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表