使用 -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
做同样的事情,但是为您做这件事并使单行代码更清晰。
我想我的问题标题基本上涵盖了它。这是一个人为的例子,它试图过滤完全等于参数化字符串的输入行,基本上是 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
.
我想我真正想要的是一个选项,它会在代码周围创建一个隐式 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-loopperl -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
做同样的事情,但是为您做这件事并使单行代码更清晰。