我正在尝试使用 GetOptions 中的 GetOpt::Long 函数来调用接受参数的子例程。但是,无论是否在命令行上指定了该选项,都会调用子例程。如果未将参数传递给 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 行中调用子例程的正确语法,以及理解为什么观察到的行为是发生。

最佳答案

模块 expects a code reference ,单独使用子名称( \&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 并在子 cb() 调用 sub1(...) 。此回调传递选项名称和值(或名称、键和值,如果是散列),并且不接受其他参数。因此,您无法以任何方式动态解析要传递给 sub1() 的参数。

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

当您尝试“传递不再是 coderef 的参数”但执行 sub 时,然后获取其返回的引用;与 \sub()\( sub() ) 相同。这可以通过
perl -wE'sub tt { say "@_"; return "ret" }; $r = \&tt("hi"); say $$r'

什么打印品

你好
回复

虽然这不是一种引用方式,但让我仍然警告 surprises

关于perl GetOptions,接受参数的选项触发子例程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47298922/

10-10 12:36