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

Is it possible to pass command-line arguments to @ARGV when using the -n or -p options?

我想我的问题标题基本上涵盖了它。这是一个人为的例子,它试图过滤完全等于参数化字符串的输入行,基本上是 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 (<>) { ... } 循环,菱形运算符吞噬了文件名的所有 command-line 参数。因此,虽然从技术上讲 bb 参数 did 达到了 @ARGV,但整个程序失败了,因为参数被 选中了由钻石运营商提供。最终结果是,在使用 -n.

时无法将 command-line 参数传递给 Perl 程序

我想我真正想要的是一个选项,它会在代码周围创建一个隐式 while (<STDIN>) { ... } 循环,因此 command-line 参数不会被用于文件名,但这样的事情确实如此不存在。

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

1: BEGIN { ... } 要复制和清除的块 @ARGV.

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

2: 手动编码 one-liner.

中的 while-loop
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 { ... } 块解决方案是不可取的,因为它在 one-liner 中构成了一个不和谐的上下文切换,有点冗长,并且需要弄乱特殊变量 @ARGV

我认为手动 while-loop 解决方案更像是 non-solution,因为它完全放弃了 -n 选项,关键是我希望能够使用-n 选项带有 command-line 个参数。

环境变量解决方案也是如此;关键是我希望能够将 command-line 参数与 -n 选项一起使用。

有没有更好的方法?

你基本上都认出来了。至少我知道,您唯一错过的是传递开关参数(而不是位置参数)的选项:

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

您也可以使用众多 getopt 模块之一来代替 -s。这基本上与在主程序循环之前在 BEGIN {} 块中操作 @ARGV 做同样的事情,但是为您做这件事并使单行代码更清晰。