Perl Getopt::Long和Pod::用法存在问题

Perl Getopt::Long和Pod::用法存在问题,perl,Perl,下面是我的perl脚本中的内容。如果我使用参数运行它,它会像@ARGV==0一样打印用法。有人知道为什么吗 GetOptions ( 'param=s' => \my $opt_parameter, 'o=s' => \my $opt_o, 'r=s' => \my $opt_r, 'g=s' => \my $opt_g, 'len=i' => \my $opt_rl,

下面是我的perl脚本中的内容。如果我使用参数运行它,它会像@ARGV==0一样打印用法。有人知道为什么吗

GetOptions (
    'param=s'   => \my $opt_parameter, 
    'o=s'       => \my $opt_o,
    'r=s'       => \my $opt_r,
    'g=s'       => \my $opt_g,
    'len=i'     => \my $opt_rl,
    'ct=i'      => \my $opt_ct,
    'help|?'    => \(my $opt_help = 0),
    'man'       => \(my $opt_man = 0),
) or pod2usage(2); 

pod2usage(1) if $opt_help;
pod2usage(-verbose => 2) if $opt_man;
pod2usage("$0: No files given.") if (@ARGV == 0);
发出命令:

script.pl -o=value1 -r=value2 -g=value3 -len=integervalue1 -ct=integervalue2

你可能面临这个问题

命令行不是由GetOptions分割的,而是由命令行分割的 解释器(CLI)。在Unix上,这是shell。在Windows上,它是 COMMAND.COM或CMD.EXE。其他操作系统具有其他CLI。它是 重要的是要知道,当 命令行包含特殊字符,特别是引号或 反斜杠。例如,对于Unix shell,可以使用单引号 (')和双引号(“)将单词组合在一起 Unix上的替代方案是等效的:

  • “两个字”
  • “两个字”
  • 两个字
如有疑问,请在Perl程序前插入以下语句:


验证CLI如何将参数传递给程序。

多亏了Adam Taylor,我才解决了问题。他指出,在处理我的参数后,我的@ARGV是空的,这是真的。如果我把我的语句:

pod2usage("$0: No files given.") if (@ARGV == 0);

在我的GetOptions语句之前,它的工作原理是在参数传递之前检查@ARGV。感谢大家帮助我排除故障!

以下工作原理与我假设您希望的一样:

#!/usr/bin/env perl

use strict;
use warnings;

use Getopt::Long;
use Pod::Usage;

my ($opt_parameter, $opt_o, $opt_r, $opt_g, $opt_rl, $opt_ct);
my $opt_help = 0;
my $opt_man = 0;
my @files;

GetOptions (
        '<>'      =>    sub { push @files, shift },
        'param=s' =>    \$opt_parameter,    
        'o=s'       =>  \$opt_o,
        'r=s'       =>  \$opt_r,
        'g=s'       =>  \$opt_g,
        'len=i'     =>  \$opt_rl,
        'ct=i'      =>  \$opt_ct,
        'help|?' =>     \$opt_help,
        'man'   =>      \$opt_man) or pod2usage(2); 

pod2usage(1) if $opt_help;

pod2usage(-verbose => 2) if $opt_man;

pod2usage("$0: No files given.") if (@files == 0);

print "$_\n" for ( @files );
区别在于:

  • (添加了shebang和
    use
    s)

  • $opt_参数
    重命名为
    $opt_参数
    使用严格;
    应该捕捉到这一点)

  • 添加了一个
    '
    选项和
    @files
    来存储。

  • 查看
    @文件的大小,而不是
    @ARGV
    (后者已被
    GetOptions()
    清除)

  • (最后打印
    @files
    ,看看是否有效。)

  • 双破折号表示长选项

  • 将整数赋予整数类型选项(
    --len
    --ct
    );字符串将导致解析失败

  • (在
    之后换行,以便能够读取代码。)

    • 从@ARGV解析并删除args

      从文档中:


      Getopt::Long模块实现了一个名为GetOptions()的扩展Getopt函数。它从@ARGV解析命令行,识别并删除指定的选项及其可能的值。

      您可以添加用于调用perl脚本的命令行吗?您没有向脚本传递任何文件。Getopts处理完命令行参数后,
      @ARGV
      中没有任何内容>1) 不应该
      或pod2用法(2);
      还是死“。。。";?2) 哪里使用了
      $opt_参数
      ?3) 你是否使用严格的代码;使用警告?1。如果没有提供参数,我想打印用法。2. $如果存在包含参数和值列表的文件,则可以选择使用opt_参数。3.是的,我同时使用strict和warnings.@Adam-我正在将文件名传递给$opt_g。不管怎样,我相信“@ARGV”保存所有参数(如果提供了参数),我这样做的时候,“@ARGV”中应该有一些内容。
      GetOptions()
      将解析
      @ARGV
      。这行只是声明了一些变量。@ChankeyPathak我不知道你完全改变的答案会如何应用,因为OP的命令既不包含空格也不包含引号。啊,这就是问题所在。接受您自己的答案,使其不再属于“未回答”类别。但是,如果您使用
      -o值运行脚本,则
      标量(@ARGV)
      将是
      2
      ,尽管没有提供“文件”。在您的情况下,任何选项都足以通过测试,您肯定希望GetOpt::Long在前面一点一点地删除所有有效参数,直到完成为止……然后您的@ARGV拥有命令行的剩余参数,通常是文件。我解释了为什么在GetOptions()之后@ARGV==0,问题中的命令行在选项后没有任何其他参数…此答案与OP自己的答案有相同的问题(因为它们实际上是相同的):如果使用
      -o值运行脚本,则
      标量(@ARGV)
      将为2,尽管没有“文件”您的构造仍然会在不可靠的状态下运行,当我传递参数
      --len=10
      时,它将成功跳过开始时的测试,选项被蚕食,将@ARGV留空---在通过GetOpt::Long解析@ARGV之前,您永远不想检查它,这违背了模块的全部目的。您肯定希望模块首先处理所有选项,然后处理剩余内容,如文件名。这是一个错误的建议,很抱歉说GetOptions只清除匹配的选项,未匹配的参数仍保留在@ARGV中
      #!/usr/bin/env perl
      
      use strict;
      use warnings;
      
      use Getopt::Long;
      use Pod::Usage;
      
      my ($opt_parameter, $opt_o, $opt_r, $opt_g, $opt_rl, $opt_ct);
      my $opt_help = 0;
      my $opt_man = 0;
      my @files;
      
      GetOptions (
              '<>'      =>    sub { push @files, shift },
              'param=s' =>    \$opt_parameter,    
              'o=s'       =>  \$opt_o,
              'r=s'       =>  \$opt_r,
              'g=s'       =>  \$opt_g,
              'len=i'     =>  \$opt_rl,
              'ct=i'      =>  \$opt_ct,
              'help|?' =>     \$opt_help,
              'man'   =>      \$opt_man) or pod2usage(2); 
      
      pod2usage(1) if $opt_help;
      
      pod2usage(-verbose => 2) if $opt_man;
      
      pod2usage("$0: No files given.") if (@files == 0);
      
      print "$_\n" for ( @files );
      
      -o=value1 -r=value2 -g=value3 --len=1 --ct=2 file1 file2