[Perl Other] 使用 Perl 的命令行来替换 awk , sed 之类

Aug 28th, 2009

转载本站文章请注明,转载自:扶凯[http://www.php-oa.com]

本文链接: http://www.php-oa.com/2009/08/28/perl-awk-sed.html

前言,做为系统管理人员,每天面对大量的事情,所以他们想了很多法子来自动化,单行脚本就是其中之一,但到后来,他们发现要学的东西,又多又乱,比如sed和awk,单这二样,就可以写一本书出来.所以Larry Wall写了perl来替换学习n多的软件和语言,以perl来完成所有.

我就是其中一个被sed,awk之类众多软件烦到的人,所以下决心学会perl,以后就在也不用管其它的这些乱又杂的软件.如下就是perl做命令行的一些简单的介绍.

Perl 作为命令行实用程序

http://www.ibm.com/developerworks/cn/linux/sdk/perl/l-p101/index.html

http://www.ibm.com/developerworks/cn/linux/sdk/perl/l-p102/index.html

作者提到的很重要的一点是:有经验的程序员不应回避快速而又难看的解决方案.

Perl 单行命令示例

 我们先看看perl如何接收用户的参数.如下,Dumper模块不用理会,只是它会给数据结构打印出来.shell给接收到的参数都放到了@ARGV这个数组.

$ perl -MData::Dumper -e'print Dumper \@ARGV' a b -w
$VAR1 = [
          'a',
          'b',
          '-w'
        ];

如上,perl可以直接接收到shell命令行的参数.“-e”后的任何内容并将它当作脚本来运行.“-M”参数表示获取其后的任何内容并将该内容作为模块导入,类似于正规脚本中的“use ModuleName”.我们可以看到象所有的 Perl 程序一样, 只有程序的最后一行不需要以 ; 结尾. 注:-e在单行命令中非常的重要,做单行命令时一定要加入 在使用perl的单行命令时要注意使用”,不要使用"".其实sed和awk也是一样,当然这只是一个建议.看下面的例子就能明白

$ perl -e 'print "$$\n"'
5719

$$在perl中表示当前的pid,如果使用的是单引号,其中还可以放双引号,还有变量,重要的是,这些变量不用担心被shell转义.

开始,我们来看看我会有可能会用到的perl单行命令中的一些参数

-e 指定字符串以作为脚本(多个字符串迭加)执行
-M 导入模块
-I 指定目录以搜索标准位置前的模块 整洁性
-w 打开警告 -Mstrict 打开严格编译指示(pragma) 数据 -0 (这是个零)指定输入记录分隔符
-a 将数据分割成名为 @F 的数组 -F 指定分割时 -a 使用的模式(请参阅 perldoc -f split)
-i 在适当的位置编辑文件(请参阅 perldoc perlrun 以获取大量详细信息)
-c 进行perl的语法检查,但不执行perl命令.
-F 把缺省的分离号改为你想要的.例如把分离号定为非字符
-l 使用 -l 有两个效果,第一自动 chomp 输入分隔号,第二 把$/ 值付给 $\ ( 这样 print 的时候就会自动在末尾加 \n )
-n 使用 <> 将所有 @ARGV 参数当作文件来逐行运行,会将读入的内容隐式的逐一按行来遍历文件.
每一行将缺省保存在 $_ -p 和 -n 一样,但是还会打印 $_ 的内容 请注意 -p 开关和 -n 开关的使用.
当您想显式打印数据时,使用 -n 开关. -p 开关隐式地将 print $_ 语句插入到 -n 开关所产生的循环中.因此, -p 开关更适用于对文件进行的 完全处理,而 -n 开关更适用于 选择性文件处理,这样的处理只需打印特定数据.

 

常用的 Perl 单行实例
为了加清了解,可以都测试一下.程序能做的任务事都能做,所以比 Shell 强大,性能更好,更加方便

查找修改访问几天前 or 几天内的内容
    这使用了个 glob 是找文件名,可以任意订自己的通配符

$ perl -le 'print for grep { 7 > -M } glob "*"'

修改当前file文件中的文件
    这个很帅,不生成中间文件,速度很快.记住 -i 开关,因为它让你原地编辑文件.

$ perl -pi -e's/aaa/bbb/' filename

象grep一样过滤文件中需要的内容
     这个地方,使用了-n,所以一次是做一行的操作,直到整个文件读完.另外,在管道时,-n也会一样,来遍历管道送过来的内容.

$ perl -ne 'print if /^aaaaa/' filename

 显示文件行号
     这个例子中的,没用-ne,只是命令写成了-n -e,其实一样,这个例子中,是给当前文件中的内容都加一个行号打印出来.注:$.表示当前行号

$ perl -n -e 'print "$. - $_"' filename

显示行号并打印
     这个其实和上面一样,分别只是使用了-p替换了-n,这个有个什么好处啦,别的地方都一样,但-p按行来遍历完文件后,会给$_打印出来.

$ perl -pe '$_ = "$.  $_"' filename

分割字符域
    大家还记得awk分割域(awk ‘{i = NF – 1; print $1 + $i}’)啊,是不是很方便,下面我们来看看perl
这个神奇的地方在于-a,使用-a后.因为-n分行读进来,然后-a给数据分割成@F的数组.

$ perl -lane 'print $F[0] + $F[-2]'

查找一个区间的内容
     打印正则中从$start到$end的地方,这个别的程序相当不好操作

$ perl -ne 'print if /^START$/ .. /^END$/'

有效地打印数字范围中的行

$ perl -ne 'print if $. >= 15; exit if $. >= 17;'

原地修改文件,并备份
     -i 开关的神奇之处在于它对 @ARGV 中的每个文件都用该脚本对该文件输出所产生的文件版本进行替代

$ perl -p -i.bak -e 's/\bfoo\b/bar/g' *.c

给文件中的内容反向排序,比如文件中有fukai,就会变成iakuf

$ perl -ne 'print scalar reverse $_' test

生成任意位的随机字符,例子中是 4 位

perl -le 'print join "",map {("a" .. "z",0 .. 9)[rand 36]} ( 1.. 4)'

Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪 ViVi 365Key 网摘 天极网摘 和讯网摘 博拉网 POCO 网摘 饭否 QQ 书签 Digbuzz 我挖网 Mister Wong
  1. 纸黄金走势图
    Aug 28th, 2009 at 13:32
    Reply | Quote | #1

    = =# 怎么今天逛的都是这么专业的博客。。 。 佩服之!

  2. zhousir
    Oct 27th, 2010 at 07:08
    Reply | Quote | #2

    呵,你的技术blog写的真好,同为技术人员,你的blog给了我不少帮助啊

  3. robi
    Jan 11th, 2012 at 02:46
    Reply | Quote | #3

    $ perl -ne ‘print if /^START$/ .. /^END$/’

    这个还是没法理解可以具体解释下吗?thx

  4. lysu
    Jan 11th, 2012 at 02:47
    Reply | Quote | #4

    打印正则中从$start到$end的地方,这个别的程序相当不好操作

    $ perl -ne ‘print if /^START$/ .. /^END$/’

    这个没能理解,请解释下 thx

  5. 扶 凯
    Jan 12th, 2012 at 03:43
    Reply | Quote | #5

    这个是找一个范围的东西,比如
    ddd
    aaa
    bbb
    ccc
    要找到 aaa 到 ccc 之间的东西