Search code examples
perlgetoptgetopt-long

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

How do I make getopts flag an error when a bad option is passed without a dash? I was expecting that no_pass_through will take care of this. What am I missing?


Solution

  • Getopt::Long just extracts the options. It's up to you to validate the value of those options and the non-option arguments (which are left in @ARGV).

    Specifically, if you want to make sure that only options have been passed, then you can use

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

    What I use:

    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());
    

    Helpers:

    use File::Basename qw( basename );
    
    sub help {
       my $prog = basename($0);
       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($0);
       say STDERR "Try '$prog --help' for more information.";
       exit(1);
    }