每个Perl黑客应该了解perl -ne?

Ano*_*don 19 perl command-line

我多年来一直在使用带有-ne选项的Perl命令行,主要用于处理sed不能的方式的文本文件.例:

cat in.txt | perl -ne "s/abc/def/; s/fgh/hij/; print;" > out.txt
Run Code Online (Sandbox Code Playgroud)

我不知道我在哪里学到了这一点,并且今天只读了perlrun并发现还有其他形式(perl -pe例如).

我还应该知道什么perl -ne

mob*_*mob 24

perl -ne 'CODE' 相当于该计划

while (<>) {
    CODE
}
Run Code Online (Sandbox Code Playgroud)

perl -ane 'CODE'并且perl -F/PATTERN/ -ane也是了解的好习惯.他们相当于

while (<>) {
    @F = split /\s+/, $_;
    CODE
}
Run Code Online (Sandbox Code Playgroud)

while (<>) {
    @F = split /PATTERN/, $_;
    CODE
}
Run Code Online (Sandbox Code Playgroud)

示例: 高级grep:

perl -ne 'print if/REGEX1/&&!/REGEX2/&&(/REGEX3/||/REGEX4/&&!/REGEX5/)' input

perl -F/,/ -ane 'print if $F[2]==4&&$F[3]ge"2009-07-01"&&$F[3]lt"2009-08-01"' file.csv
Run Code Online (Sandbox Code Playgroud)


这里使用不匹配的括号的一个特别聪明的例子.

  • 我猜"F"代表字段.我认为*它也可能是一个awk惯例. (2认同)

dao*_*oad 13

有一件重要的事情需要了解perl -neperl -pe脚本:它们隐含地使用<>.

"为什么这很重要?" 你可能会问.

魔术<>运算符使用2 arg形式的open.如果你还记得,2 arg open包含模式的规范,文件名在一个参数中.旧样式调用open FILE, $foo易受操作文件模式的影响.在此上下文中一个特别有趣的模式是|- 您打开管道的句柄到您执行的进程.

你可能会想到"大不了!",但确实如此.

  • 想象一下root执行的一个cron作业,用于在某个目录中修改日志文件.
  • 该脚本被调用为script *.
  • 想象一下名为该目录的文件|rm -rf /.

怎么了?

  1. shell扩展了*我们得到的script file_1 file_2 '|rm -rf /' file_4
  2. 脚本处理file_1file_2.
  3. 接下来它打开STDIN的句柄rm -rf /.
  4. 随后是大量的磁盘活动.
  5. file_4 不再存在,所以我们无法打开它.

当然,可能性是无穷无尽的.

您可以在Perlmonks上阅读有关此问题的更多讨论.

故事的寓意:小心<>操作员.

FWIW,我刚刚确认这仍然是perl 5.10.0的问题.

  • @Roboprog 有一个 CPAN 模块:[`ARVG::readonly`](http://search.cpan.org/~davidnico/ARGV-readonly-0.01/lib/ARGV/readonly.pm)。 (2认同)

Rob*_*rog 6

您可以指定多个-e子句.有时我有一个命令行开始增长,因为我改进了搜索/提取/破坏操作.如果你输入错误的内容,你会得到一个"行号",告诉你哪个-e有错误.

当然,有些人可能会争辩说,如果你有一个或两个以上的-e子句,也许你应该把它放在一个脚本中,但是有些东西真的只是扔掉了,所以为什么要费心呢.

perl -n -e 'if (/good/)' -e '{ system "echo $_ >> good.txt"; }' \
-e 'elsif (/bad/)' -e '{ system "echo $_ >> bad.txt"; }' \
-e 'else' -e '{ system "echo $_ >> ugly.txt"; }' in.txt another.txt etc.txt
Run Code Online (Sandbox Code Playgroud)

大概你会做一些比grep/egrep更简单的东西到3个文件中:-)