Getopts 在没有破折号的情况下标记错误的选项

Getopts to flag bad options without dash

Getopt::Long::Configure("no_pass_through");
my %opts = ();
GetOptions(\%opts,
           'opt1=s',
           'opt2=s',
           'opt3'
          );

test.pl bad_option_without_dash

当传递的错误选项没有破折号时,如何让 getopts 标记错误?我原以为 no_pass_through 会解决这个问题。我错过了什么?

Getopt::Long operates only on options: arguments starting with hyphens. Without passthrough (no_pass_through is the default) it will remove them from @ARGV,留下任何非选项参数供您处理。如果您期望没有非选项参数,则如果在调用 GetOptions.

后仍有任何参数,则可以确定选项传递不正确
die "Usage: [=10=] [--opt1=string] [--opt2=string] [--opt3]\n" if @ARGV;

GetOptions 的 return 值也很有用,因为它将指示是否发现任何无法识别或无效的选项。

GetOptions(...) or die "Usage: [=11=] ...\n";

选项用前导破折号(连字符)表示;参数不是。

您可能会发现 Getopt::Long Argument-callback 有用:

A special option 'name' <> can be used to designate a subroutine to handle non-option arguments. When GetOptions() encounters an argument that does not look like an option, it will immediately call this subroutine and passes it one parameter: the argument name.

Getopt::Long 只是提取选项。由您来验证这些选项和非选项参数(留在 @ARGV 中)的值。

具体来说,如果你想确保只传递了选项,那么你可以使用

@ARGV == 0
   or die("usage\n");

我用的是:

use Getopt::Long qw( );

my ( $opt_opt1, $opt_opt2, $opt_opt3 );

sub parse_args {
   ( $opt_opt1, $opt_opt2, $opt_opt3 ) = ();

   Getopt::Long::Configure(qw( posix_default ));
   Getopt::Long::GetOptions(
      'help|h|?' => \&help,
      'opt1=s'   => $opt_opt1,
      'opt2=s'   => $opt_opt2,
      'opt3'     => $opt_opt3,
   )
      or usage();

   # Validate $opt_* here if necessary.

   !@ARGV
      or usage("Too many arguments.");

   return @ARGV;
}

sub main {
   # my () = @_;   # This program doesn't accept non-option args.
   ...
}

main(parse_args());

帮手:

use File::Basename qw( basename );

sub help {
   my $prog = basename([=12=]);
   print
"Usage:
  $prog [options]
  $prog --help

Options:
  --opt1 FOO
      ...

  --opt2 BAR
      ...

  --opt3
      ...
";
   exit(0);
}

sub usage {
   if (@_) {
      my ($msg) = @_;
      chomp($msg);
      say STDERR $msg;
   }

   my $prog = basename([=12=]);
   say STDERR "Try '$prog --help' for more information.";
   exit(1);
}