上一节中介绍了用perl命令行结合正则表达式批量修改文件的基本方法,基本的命令行模式如下:

perl -p -i.bak -e "s/搜索/替换/参数" 文件名

本节先解释一下各个参数的意义。

-e 使perl可以在命令行直接运行一小段语句,-e 后面跟着的就是要执行的语句内容,比如:

perl -e "print 1+2;"

执行后会输出3。

在介绍-p参数之前,先介绍一下-n。-n 参数形成了一个循环,使得通过命令行可以逐行处理指定的文件。比如:

Windows环境: perl -n -e "print \"$.: $_\"" file1

注:在Windows环境下,如果由双引号括起来的命令行参数中出现双引号时,可以用反斜杠转义。

Linux环境: perl -n -e 'print "$.: $_"' file1

注:在Linux环境下,命令行参数既可以用双引号也可以用单引号来包含,需要转义时也可以用反斜杠“\”。但是,要特别注意的是,如果是双引号的话,其中的“$name”形式的内容会被相应的环境变量的值替换,所以建议默认采用单引号。

等价于以下perl程序:

LINE:
  while (<&gt ;)  {
    print "$.: $_"
  }

也就是会把指定文件的内容每行的前面加个行号之后输出。(<>打开命令行参数中文件名制定的文件,一行行读取,每一行的内容保存在perl的缺省变量$_中,而$.也是perl的一个特殊变量,表示当前的行号。)

-p 在 -n 的基础上,确保缺省参数的值会被输出,比如:

Windows环境: perl -p -e "$_ = \"$.: $_\"" file1

Linux环境: perl -p -e '$_ = "$.: $_"' file1

等价于以下perl程序:

LINE:
  while (<&gt ;)  {
    $_ = "$.: $_"
  } continue {
    print or die "-p destination: $!\n";
  }

作用和之前用-n参数的例子相同。

-i 参数表示原位编辑(inplace edit),输出的结果直接写回到原始文件中,-i.bak可以创建原文件的备份,当然,也可以使用-i.old等来为备份文件指定别的扩展名。(其实,perl解释器在读取文件之前先将原文件更名为对应备份文件名,再创建以原文件名为名的新文件接收输出结果。)

解释了以上参数以后,再来理解以下用来做正则表达式批量替换的命令行就容易了:

perl -p -i.bak -e "s/搜索/替换/参数" 文件名

在perl中,作为一个单一语句,“s/搜索/替换/参数 ”等价于 “$_ =~ s/搜索/替换/参数”,对缺省参数进行正则表达式替换运算。-p -i.bak的组合使得perl解释器一行一行循环读取命令行参数指定的文件,进行正则表达式替换运算后输出,输出结果写入原文件名指定的文件中,原文件备份到对应的.bak文件中。

做为本节的结束,我列出了几个小例子,供大家参考:

perl -p -i.bak -e "s/(\d\d)\/(\d\d)\/(\d{4})/\3-\1-\2/g" filename

将filename指定文件中的mm/dd/yyyy格式的日期转换为yyyy-mm-dd格式。比如:10/31/2008将被转换为2008-10-31。分别捕获月日年后调换顺序并使用“-”进行拼装。

perl -p -i.bak -e "s/ +$//" filename

将filename指定文件中的每一行的行尾空格清除。由于每一行只可能匹配一次行尾空格,所以正则表达式中不需要参数g。

perl -p -i.bak -e "s/\b(colo)u(r)\b/\1\2/gi" filename

将filename指定文件中的所有英式写法的colour改成美式写法的color,不区分大小写(由正则表达式的i参数声明),而且保持原有的大小写。将原有的colo和r分别捕获后再拼装回来。

perl -p -i.bak -e "s/(?<=\bcolo)u(?=r\b)//gi" filename

和上例的作用相同,不过采用了零宽断言,整个正则表达式仅匹配了u一个字母后将其替换为空。

perl -p -i.bak -e "s{catch\s*\(\s*(?:System\.)?Exception\b.*\K$}{ //TODO: 检查异常处理}g" program.cs

上面的这个例子可以找到C#程序文件program.cs中所有直接捕获Exception类型异常的语句并在当行结尾处添加一个TODO注释。(程序员在写异常处理代码时,应该尽可能捕获特定的异常进行处理。一般情况下,不应捕获所有异常进行处理。)此例中有几个值得注意的地方。首先是正则表达式的格式不是之前一直在用的“s/搜索/替换/参数”,而是“s{搜索}{替换}参数”,这样在正则表达式有很多“/”时避免过多的转义符,perl还支持多种不同的格式来书写正则表达式,有兴趣的话可以查看相关资料。再注意一下“\K”,它表示在它之前的所有内容都不成为匹配结果的一部分,类似于它之前的部分都成为了回顾零宽断言。

下一节,将结合更复杂的示例介绍进一步介绍使用Perl和正则表达式批量修改文件的方法,将会引入新的Perl命令行参数。

标签:,