我在网上发现了很多Perl单行。有时我想将这些单行转换成脚本,否则我会忘记单行的语法。
例如,我正在使用以下命令(来自nagios.com):
tail -f /var/log/nagios/nagios.log | perl -pe 's/(\d+)/localtime($1)/e'
我要用这样的东西替换它:
tail -f /var/log/nagios/nagios.log | ~/bin/nagiostime.pl
但是,我无法找出将这些内容快速投入脚本的最佳方法。有没有人能够快速将这些单行内容放入Bash或Perl脚本中?
答案 0 :(得分:38)
您可以将任何Perl one-liner转换为完整脚本,方法是将其传递给生成Perl源代码的B::Deparse
编译器后端:
perl -MO=Deparse -pe 's/(\d+)/localtime($1)/e'
输出:
LINE: while (defined($_ = <ARGV>)) {
s/(\d+)/localtime($1);/e;
}
continue {
print $_;
}
这种方法比手动解码命令行标志的优势在于,这正是Perl解释脚本的方式,所以没有猜测。 B::Deparse
是核心模块,因此无需安装。
答案 1 :(得分:8)
看看perlrun:
-p
导致Perl在程序周围采用以下循环,这使得它迭代文件名参数,有点像sed:
LINE: while (<>) { ... # your program goes here } continue { print or die "-p destination: $!\n"; }
如果由于某种原因无法打开由参数命名的文件,Perl会向您发出警告,然后转到下一个文件。请注意,线条会自动打印。打印期间发生的错误被视为致命错误。要禁止打印,请使用-n开关。 -p覆盖-n开关。
BEGIN和END块可用于在隐式循环之前或之后捕获控件,就像在awk中一样。
所以,只需要获取这段代码,将代码插入“#your program goes here”行,并且中提琴,你的脚本就准备好了!
因此,它将是:
#!/usr/bin/perl -w
use strict; # or use 5.012 if you've got newer perls
while (<>) {
s/(\d+)/localtime($1)/e
} continue {
print or die "-p destination: $!\n";
}
答案 2 :(得分:7)
那个真的很容易存储在脚本中!
#! /usr/bin/perl -p
s/(\d+)/localtime($1)/e
-e
选项引入了要执行的Perl代码 - 您可能会将其视为命令行上的脚本 - 因此将其删除并将代码粘贴在正文中。将-p
留在shebang(#!
)行。
一般来说,最安全的做法是坚持shebang系列中最多一个“丛”选项。如果你需要更多,你总是可以将它们的等价物扔进BEGIN {}
块。
不要忘记chmod +x ~/bin/nagiostime.pl
你可以获得一点点发烧友并嵌入tail
部分:
#! /usr/bin/perl -p
BEGIN {
die "Usage: $0 [ nagios-log ]\n" if @ARGV > 1;
my $log = @ARGV ? shift : "/var/log/nagios/nagios.log";
@ARGV = ("tail -f '$log' |");
}
s/(\d+)/localtime($1)/e
这是有效的,因为-p
为您编写的代码使用Perl的“魔术”(2参数)open
来专门处理管道。
没有参数,它会转换nagios.log
,但您也可以指定其他日志文件,例如,
$ ~/bin/nagiostime.pl /tmp/other-nagios.log
答案 3 :(得分:4)
或者,这是你的oneliner作为一个脚本::)
#!/usr/bin/bash
# takes any number of arguments: the filenames to pipe to the perl filter
tail -f $@ | perl -pe 's/(\d+)/localtime($1)/e'
答案 4 :(得分:3)
#!/usr/bin/env perl
while(<>) {
s/(\d+)/localtime($1)/e;
print;
}
while循环和print是-p自动为你做的。
答案 5 :(得分:3)
如果你想保留一行翻译脚本并且甚至可能扩展它,那么这里有一些很好的答案,但最简单的事情可能就是:
#!/usr/bin/perl -p
s/(\d+)/localtime($1)/e
Perl将识别脚本的hashbang行上的参数,因此不是完全写出循环,而是继续使用-p继续执行隐式循环。
但是明确地编写循环并使用-w和“use strict;”如果计划将它作为编写更长脚本的起点,那就好了。