Reputation: 840
I use GetOpt to parse command-line arguments. I would like to add a new option "multi" which should get a string which looks as following: key1=abc,key2=123,key3=xwz
.
I don't know how many custom keys user want to give but he can give minimax 5
keys. Also, I would like to put it in a hash with keys.
I'm looking for a good and clean way to implement it.
For starters, I thought of using --multi {key1=abc,key2=123,key3=xwz}
but for some reason, it gets only
the first key key1=abc
. Also I tried: --multi {key1=abc},{key2=123},{key3=xwz}
but it feels kind of messy. I want to give the user the possibility to add arguments with -
like key1=./some_script.pl --help
. Part of the code:
my %arg;
GetOptions(
"multi=s" => \$arg{"multi"},
}
Then I would like to somehow put those keys in the hash so it will be easy to use them. So I thought of using: $arg{"multi"}{"key3"}
in order to get the value of key3
.
How should I approach this feature? What is the cleanest way to do so?
To summarize it:
key1=abc,key2=123,key3=xwz
, without using a file (giving options, not in a file way)? Meaning - how would you like, as a user of the script, to give those fields?multi
key.Expected output: I would like to have a hash which looks like this: $arg{"multi"}{"key3"}
and returns xwz
.
Upvotes: 2
Views: 137
Reputation: 66883
One way is to assign options of key=value
format to a hash, what GetOpt::Long allows. Even better, as this functionality merely needs a hash reference, it turns out that you can have it assign to a hashref that is a value inside a deeper data structure. You can make direct use of that
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
use Data::Dump qw(dd);
my %args;
$args{multi} = {};
GetOptions( 'multi=s' => $args{multi} ) or die "Bad options: $!";
dd \%args;
With multiple invocations of that option the key-value pairs are added
script.pl --multi k1=v1 --multi k2=v2
and the above program prints
{ multi => { k1 => "v1", k2 => "v2" } }
I use Data::Dump to print complex data. Change to core Data::Dumper
if that's a problem.
While Getopt::Long
has a way to limit the number of arguments that an option takes that apparently applies only for array destinations. So you'd have to count keys to check.
Another way is to process the input string in a subroutine, where you can do practically anything you want. Adding that to the above script, to add yet another key with its hashref to %args
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
use Data::Dump qw(dd);
my %args;
$args{multi} = {};
GetOptions(
'multi=s' => $args{multi},
'other=s' => sub { $args{other} = { split /[=,]/, $_[1] } }
) or die "Bad options: $!";
dd \%args;
When called as
script.pl --multi k1=v1 --multi k2=v2 --other mk1=mv1,mk2=mv2
This prints
{ other => { mk1 => "mv1", mk2 => "mv2" }, multi => { k1 => "v1", k2 => "v2" }, }
Upvotes: 2
Reputation: 3925
The following program reads the comma-separated sub-options from the --multi
option on the command line.
#!perl
use strict;
use warnings;
use Data::Dumper;
use Getopt::Long 'GetOptionsFromArray';
my @args = ('--multi', '{key1=abc,key2=123,key3=xwz}', 'some', 'other');
my %arg;
GetOptionsFromArray(
\@args,
"multi=s" => \$arg{"multi"},
);
if( $arg{multi} and $arg{multi} =~ /^\{(.*)\}$/) {
# split up into hash:
$arg{ multi } = { split /[{},=]/, $1 };
};
print Dumper \%arg;
__END__
$VAR1 = {
'multi' => {
'key2' => '123',
'key1' => 'abc',
'key3' => 'xwz'
}
};
The program uses GetOptionsFromArray
for easy testability. In the real program, you will likely use GetOptions(...)
, which is identical to GetOptionsFromArray(\@ARGV, ...)
.
Upvotes: 3