lostbits
lostbits

Reputation: 1064

How does getopt::long work with ntermixed long/short options?

The Getopt description says that both '-' and '--' are accepted for the same option, and that short options can be bundled. Assuming that "help" is an option then:

script --help     # succeeds
script --h        # succeeds
script -h         # fails

If we have two or more options with unique first characters ("ab", "cd") the -ac does not work but --a and --c does. I have looked at all the getopt options and I thought used them correctly. Am I missing an option or have I misunderstood the getopt description?

The actual code is:

      Getopt::Long::Configure ( "gnu_getopt"
                              , "auto_abbrev"
                              , "bundling"
                              , "ignore_case_always"
                              );

      GetOptions ( 'normalize'   => \$normalize
                 , 'exclude=s'   => \@exclude
                 , 'help'        => \$help
                 , 'include=s'   => \@include
                 , 'recurse'     => \$recurse
                 , 'update'      => \$update
                 , '2update'     => \$update2
                 , 'copy'        => \$copy
                 , 'move'        => \$move

                 , 'n'           => \$normalize
                 , 'e=s'         => \@exclude
                 , 'h'           => \$help
                 , 'i=s'         => \@include
                 , 'r'           => \$recurse
                 , 'u'           => \$update
                 , '2'           => \$update2
                 , 'c'           => \$copy
                 , 'm'           => \$move
                 );

With the repeated getopts parameter allowing recognition of both "-h" and "--h". With the duplicated options things seem to work as expected, but my reading of the getopt description seems to say that the repeated code is not necessary.

Upvotes: 1

Views: 415

Answers (2)

ikegami
ikegami

Reputation: 385897

With bundling, -- must be used for long option. - can only be used for short options, of which you defined none.

You can disable bundling (nobundling after gnu_getopt, instead of bundling which is already enabled by gnu_getopt).

use Getopt::Long qw( );

for (
   [qw( --help )],
   [qw( --h )],
   [qw( -h )],
) {
   @ARGV = @$_;
   say "@ARGV";

   Getopt::Long::Configure(qw( gnu_getopt nobundling auto_abbrev ignore_case_always ));
   Getopt::Long::GetOptions(
      'normalize' => \my $normalize,
      'exclude=s' => \my @exclude,
      'help'      => \my $help,
      'include=s' => \my @include,
      'recurse'   => \my $recurse,
      'update'    => \my $update,
      '2update'   => \my $update2,
      'copy'      => \my $copy,
      'move'      => \my $move,
   );

   say $help // "[undef]";
}

Or you can use help|h defining a long (--) and a short (-) option in one go.

use Getopt::Long qw( );

for (
   [qw( --help )],
   [qw( --h )],
   [qw( -h )],
) {
   @ARGV = @$_;
   say "@ARGV";

   Getopt::Long::Configure(qw( gnu_getopt auto_abbrev ignore_case_always ));
   Getopt::Long::GetOptions(
      'normalize|n' => \my $normalize,
      'exclude|e=s' => \my @exclude,
      'help|h'      => \my $help,
      'include|i=s' => \my @include,
      'recurse|r'   => \my $recurse,
      'update|u'    => \my $update,
      '2update|2'   => \my $update2,
      'copy|c'      => \my $copy,
      'move|m'      => \my $move,
   );

   say $help // "[undef]";
}

Both programs output the following:

--help
1
--h
1
-h
1

Upvotes: 3

Polar Bear
Polar Bear

Reputation: 6798

GetOptions(
    'path|p=s'  => \$opt{path},
    'help|h'    => \$opt{help},
    'man|m'     => \$opt{man},
    'debug|d'   => \$opt{debug}
) or pod2usage(2);

Upvotes: -2

Related Questions