我试图使用GetOpt::Long
中的GetOptions
函数调用接受参数的子例程。但是,无论是否在命令行上指定了该选项,都会调用该子例程。如果没有在GetOptions
行中将参数传递给子例程,则不会发生这种意外行为。
以下是对该问题的最小说明:
如果在GetOptions
行中为子例程提供了参数,则无论是否在命令行上提供了子例程的控制选项,都将调用该子例程:
$ cat a1.pl
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
my $var="entered";
GetOptions ( "opt" => \&sub1($var) );
sub sub1 { print "sub1 $_[0]\n"; }
$ perl a1.pl --opt
sub1 entered
$ perl a1.pl
sub1 entered
相比之下,如果在GetOptions
中调用子例程时没有参数,则该子例程的行为将是适当的:
$ cat a2.pl
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
GetOptions ( "opt" => \&sub2 );
sub sub2 { print "sub2 entered\n"; }
$ perl a2.pl --opt
sub2 entered
$ perl a2.pl
我做错了什么?
PS:我知道我可以简单地设置一个变量来控制是否在GetOptions
块之后调用子例程,但我希望确定在GetOptions
行中调用子例程的正确语法,并了解为什么会出现观察到的行为。
2条答案
按热度按时间t8e9dugd1#
该模块需要一个 * 代码引用 *,并且该引用单独与子名称(
\&name
)一起使用或作为匿名子对象使用;这里没有“参数”的概念,因为你不是在进行函数调用,而是在获取一个引用(对代码)。2然后在那个代码中调用你的子函数。3详细信息如下。将选项与匿名子例程关联,在该子例程中可以调用子例程
或者使用
'opt' => \&cb
并在子函数cb()
中调用sub1(...)
。这个回调函数传递的是选项名称和值(如果是散列,则是名称、键和值),并且不接受其他参数。因此,您无法以任何方式动态解析要传递给sub1()
的参数。问题中的调用不是如何获得子例程引用;您必须只使用子例程名称
\&name
。这与Getopt
无关,它只需要一个代码引用。当你试图“传递参数”时,它不再是一个coderef,但子函数被执行,然后引用它的返回;与
\sub()
或\( sub() )
相同。这可以通过打印内容
虽然这不是一种获取引用的方法,但我仍然要警告可能的surprises(如果最终试图获取“对列表的引用”)
osh3o9ms2#
我已经有几年没有使用过Perl了,但我非常肯定这是因为
是对调用
sub1
的 result 的引用。也就是说,实际上调用
sub($var)
作为构造GetOptions
的参数列表的一部分。这看起来像是语法中的一个角落,您正在获取对该调用结果的引用。这应该可以澄清一些事情: