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

荒凉一梦 提交于 2019-12-10 17:54:02

问题


I think the title of my question basically covers it. Here's a contrived example which tries to filter for input lines that exactly equal a parameterized string, basically a Perlish fgrep -x:

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

The problem of course is that the -n option creates an implicit while (<>) { ... } loop around the code, and the diamond operator gobbles up all command-line arguments for file names. So, although technically the bb argument did get to @ARGV, the whole program fails because the argument was also picked up by the diamond operator. The end result is, it is impossible to pass command-line arguments to the Perl program when using -n.

I suppose what I really want is an option that would create an implicit while (<STDIN>) { ... } loop around the code, so command-line arguments wouldn't be taken for file names, but such a thing does not exist.

I can think of three possible workarounds:

1: BEGIN { ... } block to copy and clear @ARGV.

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

2: Manually code the while-loop in the one-liner.

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

3: Find another way to pass the arguments, such as environment variables.

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

The BEGIN { ... } block solution is undesirable since it constitutes a bit of a jarring context switch in the one-liner, is somewhat verbose, and requires messing with the special variable @ARGV.

I consider the manual while-loop solution to be more of a non-solution, since it forsakes the -n option entirely, and the point is I want to be able to use the -n option with command-line arguments.

The same can be said for the environment variable solution; the point is I want to be able to use command-line arguments with the -n option.

Is there a better way?


回答1:


You've basically identified them all. The only one you missed, that I know of at least, is the option of passing switch arguments (instead of positional arguments):

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

You could also use one of the many getopt modules instead of -s. This is essentially doing the same thing as manipulating @ARGV in a BEGIN {} block before the main program loop, but doing it for you and making it a little cleaner for a one-liner.



来源:https://stackoverflow.com/questions/39241527/is-it-possible-to-pass-command-line-arguments-to-argv-when-using-the-n-or-p-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!