Reputation: 94820
To a perl script that I am writing, there can be a lot (~50) of command line options provided. Most of them are optional, so a call will have only some of the options provided.
I am using Getopt::Long
but it does not allow me to use GetOptions
more than once. As a result, I have to use all the command line options in one GetOptions
call.
Is there some good way to group the options while using GetOptions
?
$ cat test.pl
use strict;
use warnings;
use Getopt::Long;
my ($a, $b, $c, $d);
GetOptions ('a=s' => \$a, 'b=s' => \$b);
GetOptions ('c=s' => \$c, 'd=s' => \$d);
print "a = $a\nb = $b\nc = $c\nd = $d\n";
$ perl test.pl -a=AA -b=BB -c=CC -d=DD
Unknown option: c
Unknown option: d
Use of uninitialized value in concatenation (.) or string at test.pl line 10.
Use of uninitialized value in concatenation (.) or string at test.pl line 10.
a = AA
b = BB
c =
d =
$
Upvotes: 1
Views: 2820
Reputation: 1510
The most direct answer is to use Getopt::Long::Configure like so:
use strict;
use warnings;
use Getopt::Long;
my ($a, $b, $c, $d);
Getopt::Long::Configure( qw(pass_through) );
GetOptions ('a=s' => \$a, 'b=s' => \$b);
Getopt::Long::Configure( qw(no_pass_through) );
GetOptions ('c=s' => \$c, 'd=s' => \$d);
print "a = $a\nb = $b\nc = $c\nd = $d\n";
Note that you should make sure that your last invocation of GetOptions should be configured with no_pass_through to make sure that you get warnings about unknown options.
% perl test_getop.pl -a AA -b BB -c CC -d DD -e EE
Unknown option: e
a = AA
b = BB
c = CC
d = DD
Upvotes: 2
Reputation: 37146
It may be a good idea to store your options in a hash instead:
See Getopt::Long
: Storing options values in a hash :
Sometimes, for example when there are a lot of options, having a separate variable for each of them can be cumbersome.
GetOptions()
supports, as an alternative mechanism, storing options values in a hash.To obtain this, a reference to a hash must be passed as the first argument to
GetOptions()
. For each option that is specified on the command line, the option value will be stored in the hash with the option name as key. Options that are not actually used on the command line will not be put in the hash, on other words,exists($h{option})
(ordefined()
) can be used to test if an option was used. The drawback is that warnings will be issued if the program runs under use strict and uses$h{option}
without testing withexists()
ordefined()
first.my %h = (); GetOptions (\%h, 'length=i'); # will store in $h{length}
For options that take list or hash values, it is necessary to indicate this by appending an @ or % sign after the type:
GetOptions (\%h, 'colours=s@'); # will push to @{$h{colours}}
To make things more complicated, the hash may contain references to the actual destinations, for example:
my $len = 0; my %h = ('length' => \$len); GetOptions (\%h, 'length=i'); # will store in $len
This example is fully equivalent with:
my $len = 0; GetOptions ('length=i' => \$len); # will store in $len
Any mixture is possible. For example, the most frequently used options could be stored in variables while all other options get stored in the hash:
my $verbose = 0; # frequently referred my $debug = 0; # frequently referred my %h = ('verbose' => \$verbose, 'debug' => \$debug); GetOptions (\%h, 'verbose', 'debug', 'filter', 'size=i'); if ( $verbose ) { ... } if ( exists $h{filter} ) { ... option 'filter' was specified ... }
Upvotes: 6
Reputation: 3635
Normally arrays are flattened out into a single list before being passed to a function, although some functions override this behavior. Using this you can define arrays of option groups and pass the list of arrays to GetOptions.
use strict;
use warnings;
use Getopt::Long;
my ( $opt_a, $opt_b, $opt_c, $opt_d );
my @opt_group_1 = ( 'a=s' => \$opt_a, 'b=s' => \$opt_b );
my @opt_group_2 = ( 'c=s' => \$opt_c, 'd=s' => \$opt_d );
GetOptions( @opt_group_1, @opt_group_2 );
print "a = $opt_a\nb = $opt_b\nc = $opt_c\nd = $opt_d\n";
You can combine this with storing values in a hash to prevent having to create a huge number of option variables as Zaid mentioned.
use strict;
use warnings;
use Getopt::Long;
my @opt_group_1 = ( 'a=s', 'b=s' );
my @opt_group_2 = ( 'c=s', 'd=s' );
my %opt;
GetOptions( \%opt, @opt_group_1, @opt_group_2 );
print "a = $opt{a}\nb = $opt{b}\nc = $opt{c}\nd = $opt{d}\n";
Upvotes: 0
Reputation: 62099
What's wrong with:
GetOptions(
'a=s' => \$a,
'b=s' => \$b,
'c=s' => \$c,
'd=s' => \$d,
);
Or, if they're all short, you could do:
GetOptions(
'a=s' => \$a, 'b=s' => \$b,
'c=s' => \$c, 'd=s' => \$d,
);
(Note that it's a bad idea to use $a
and $b
for anything except sort
comparisions.)
Upvotes: 1