如何检查 Perl 中传递的命令行参数的数量?

PPP*_*PPP 2 perl argv

我有一个按以下方式运行的脚本:

perl testing.pl -grid 24 -range 97   ## Here, arguments passed are processed via getopt::Long module.
Run Code Online (Sandbox Code Playgroud)

现在,我想检查传递给脚本的命令行参数的数量。预期是 2。但我得到 0。

我在脚本(testing.pl)中使用了下面的代码来提取参数的数量:

my $totalCmdLineArg = $#ARGV + 1;
print "$totalCmdLineArg is total command line arguments\n";
if ($totalCmdLineArg <= 0 ) {
    $defaultmode=1;
} else {
    $defaultmode=0;
}
Run Code Online (Sandbox Code Playgroud)

在这里,我得到“0 是命令行参数总数”作为输出。我希望“2 是总命令行参数”作为输出。我怎样才能得到预期的答案?

注意:有 100 多个参数,其中任何一个都可以传递。

Dad*_*ada 6

GetOptions被调用后你就不能计算选项了。GetOptions删除它识别的选项@ARGV。引用其文档

命令行选项取自数组@ARGV。完成 GetOptions 后,@ARGV 将包含命令行的其余部分(即非选项)。

此外,GetOptions不计算它解析了多少个选项。如果您需要有说服力,请查看来源。

因此,如果您想计算有多少个选项传递给您的程序,您必须在调用之前GetOptions手动执行此操作。

如果命令行上的所有参数都具有形式--option xxx,那么您可以简单地执行以下操作(调用之前GetOptions):

my $totalCmdLineArg = grep { /^--/ } @ARGV
Run Code Online (Sandbox Code Playgroud)

--然而,这忽略了in 本身@ARGV标记选项列表结尾的事实。如果您的命令行类似于perl prog.pl --opt1 v1 --opt2 v2 -- some additional --argumentsthen--并且--arguments实际上不是选项(对于GetOptions)。要处理这种情况,您必须编写如下内容:

my $totalCmdLineArg = 0;
for (@ARGV) {
    last if $_ eq '--';
    $totalCmdLineArg++ if /^--/;
}
Run Code Online (Sandbox Code Playgroud)

-但是,这并没有考虑到单个选项可用于启动选项,并且可用于组合多个选项(is$Getopt::Long::bundling非零)的事实。您必须调整上面的代码来处理这种情况。


仅在最后的手段(不要在生产中使用,可能随时中断):
如果您正在使用bundling和其他复杂功能Getopt::Long,您可以稍微修改一下来计算实际找到的选项数量Getopt::Long。在内部,GetOptions调用FindOption实际寻找选项。您可以重新定义它来计算找到的选项数量:

my $opt_count = 0;
{
  no warnings qw(redefine prototype);
  my $original_FindOption = \&Getopt::Long::FindOption;
  *Getopt::Long::FindOption = sub {
    my @ret = &$original_FindOption;
    if ($ret[0] && defined $ret[1]) {
      $opt_count++;
    }
    return @ret;
  };
}
Run Code Online (Sandbox Code Playgroud)

请注意,这是一种非常脆弱的方法:FindOption不是 的公开 API 的一部分Getopt::Long,因此可能会在版本之间发生变化,这可能会破坏此代码。