perl GetOptions,接受参数的选项触发子例程

perl GetOptions,接受参数的选项触发子例程,perl,Perl,我试图使用GetOpt::Long中的GetOptions函数调用接受参数的子例程。但是,无论是否在命令行上指定了该选项,都会调用该子例程。如果未将参数传递给GetOptions行中的子例程,则不会发生此意外行为 下面是对问题的一个简单演示: 如果在GetOptions行中为子例程提供了参数,则不管命令行上是否提供了其控制选项,都会调用该子例程: $ cat a1.pl #!/usr/bin/perl use strict; use warnings; use Getopt::Long qw(G

我试图使用
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
行中调用子例程的正确语法,并理解观察到的行为发生的原因。

模块,这是单独使用子名称(
\&name
)或作为匿名子名称;这里没有“参数”的概念,因为您不是在进行函数调用,而是在获取(对代码的)引用。然后在代码中调用sub。详情如下

将该选项与匿名子例程相关联,您可以在其中调用子例程

use warnings;
use strict;
use feature 'say';

use Getopt::Long;

my $opt;
my $var = 'entered';

GetOptions ( 'opt' => sub { $opt = 1; sub1($var) } );

sub sub1 { say "sub1 $_[0]"; }
或者使用
'opt'=>\&cb
并在sub
cb()中调用
sub1(…)
。此回调传递选项名称和值(或者散列中的名称、键和值),不接受其他参数。因此,您无法以任何方式动态解析要传递给
sub1()
的参数

问题中的调用不是如何获得a;只能使用子例程名称
\&name
。这不是关于
Getopt
,它只需要一个代码引用

当您尝试“传递参数”时,该参数不再是coderef,而是执行sub,然后引用其返回;与
\sub()
\(sub())
相同。这一点可以从下面的例子中看出

perl -wE'sub tt { say "@_"; return "ret" }; $r = \&tt("hi"); say $$r'
什么指纹

hi ret 你好 ret
虽然这不是一种引用的方式,但我还是要提醒大家。

我已经有几年没有做过很多Perl了,但我很确定这是因为

\&sub1($var)
是对调用
sub1
的结果的引用。就是线,

GetOptions ( "opt" => \&sub1($var) );
实际上调用
sub($var)
作为构建
GetOptions
参数列表的一部分。这看起来像是语法中的一个转折点,您正在引用该调用的结果

这应该可以澄清问题:

$ perl -de0

Loading DB routines from perl5db.pl version 1.49_001
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> sub sub1 { print "sub1\n"; }

  DB<2> sub1()
sub1

  DB<3> &sub1
sub1

  DB<4> \&sub1

  DB<5> x \&sub1
0  CODE(0x804d7fe8)
   -> &main::sub1 in (eval 6)[/usr/lib/perl5/5.22/perl5db.pl:737]:2-2
  DB<6> x \&sub1()
sub1
0  SCALAR(0x804ee7f0)
   -> 1
$perl-de0
从perl5db.pl版本1.49_001加载数据库例程
编辑器支持可用。
输入h或“h”以获取帮助,或输入“man perldebug”以获取更多帮助。
main:(-e:1):0
DB sub sub1{print“sub1\n”;}
DB sub1()
sub1
DB&sub1
sub1
DB\&sub1
DB x\&sub1
0代码(0x804d7fe8)
->&main::sub1in(eval6)[/usr/lib/perl5/5.22/perl5db.pl:737]:2-2
DB x\&sub1()
sub1
0标量(0x804ee7f0)
-> 1

哇,我今天看到的第二个问题实际上包含了一个问题。我很少在一天内看到两个这样的问题。祝贺两张反对票怎么了??如果我疯了,瞎了,有人能告诉我吗?