Forget Getopt::Std for a second. How would a module (or any other code) know that bar
was an value for a
and not the first positional argument? Without a means of doing that, your grammar is ambiguous, and a parser can't be written for it.
This can be resolved in one of three ways. (Well, there are surely others.)
Solution 1 Allow the option and the flag to be repeated.
prog -a foo -a bar pos0 pos1
use Getopt::Long qw( GetOptions );
GetOptions(
'?|h|help' => \&help,
'a=s' => \my @opt_a,
)
or usage();
Solution 2 Use -a
to indicate what the positional arguments mean.
prog -a foo bar
use Getopt::Long qw( GetOptions );
GetOptions(
'?|h|help' => \&help,
'a' => \my @opt_a,
'b' => \my $opt_b,
)
or usage();
( $opt_a ? 1 : 0 ) + ( $opt_b ? 1 : 0 ) == 1
or usage("-a or -b must be specified, but not both");
my $opt_action = $opt_a ? 'a' : 'b';
@ARGV > 0
or usage("Invalid number of arguments");
Solution 3 Assume all values following -a
belong to -a
It turns out there is a standard way of marking the start of positional arguments. Using --
would distinguish option values from positional arguments.
prog -a foo bar -- pos0 pos1
use Getopt::Long qw( GetOptions );
GetOptions(
'?|h|help' => \&help,
'a=s{1,}' => \my @opt_a,
)
or usage();
However, --
is usually used to protect against positional arguments start with -
. It's a weird thing to have to protect against positional arguments not starting with -
.
It's also error-prone. People will be tempted to do the following:
prog -a foo pos0 # XXX Doesn't work as expected!
Notes:
- I used Getopt::Long. If Getopt::Std can do it too, great. I used what I knew.
- See this for sample implementation of
help
and usage
.