使用-n或-p选项时是否可以将命令行参数传递给@ARGV?

时间:2016-08-31 05:39:31

标签: perl command-line-interface command-line-arguments

我认为我的问题的标题基本上涵盖了它。这是一个人为的例子,试图过滤与参数化字符串完全相等的输入行,基本上是Perlish fgrep -x

perl -ne 'chomp; print if $_ eq $ARGV[0];' bb <<<$'aa\nbb\ncc';
## Can't open bb: No such file or directory.

问题当然是-n选项在代码周围创建了一个隐式while (<>) { ... }循环,而菱形运算符则吞噬了文件名的所有命令行参数。因此,虽然从技术上讲bb参数 到达@ARGV,整个程序都会失败,因为参数是由钻石运算符拾取。最终结果是,使用-n时无法将命令行参数传递给Perl程序。

我想我真正想要的是一个可以在代码周围创建隐式while (<STDIN>) { ... }循环的选项,因此不会对文件名采用命令行参数,但这样的事情不存在

我可以想到三种可能的解决方法:

1: BEGIN { ... }阻止复制并清除@ARGV

perl -ne 'BEGIN { our @x = shift(@ARGV); } chomp; print if $_ eq $x[0];' bb <<<$'aa\nbb\ncc';
## bb

2:手动编码单行中的while循环。

perl -e 'while (<STDIN>) { chomp; print if $_ eq $ARGV[0]; }' bb <<<$'aa\nbb\ncc';
## bb

3:找到另一种传递参数的方法,例如环境变量。

PAT=bb perl -ne 'chomp; print if $_ eq $ENV{PAT};' <<<$'aa\nbb\ncc';
## bb

BEGIN { ... }块解决方案是不合需要的,因为它在单行中构成了一些不和谐的上下文切换,有点冗长,并且需要弄乱特殊变量@ARGV

我认为手动的while循环解决方案更像是一个非解决方案,因为它完全放弃了-n选项,关键是我希望能够使用-n选项使用命令行参数。

对于环境变量解决方案也是如此;关键是我希望能够使用-n选项的命令行参数。

有更好的方法吗?

1 个答案:

答案 0 :(得分:5)

你基本上已经确定了所有这些。我唯一错过的,至少我知道的是传递switch参数(而不是位置参数)的选项:

$ perl -sne'chomp; print if $_ eq $kwarg' -- -kwarg=bb <<<$'aa\nbb\ncc';
bb

您也可以使用众多getopt模块中的一个而不是-s。这基本上与在主程序循环之前在@ARGV块中操作BEGIN {}做同样的事情,但是为你做这件事并使它对于单行程更干净。