Reputation: 2077
I have several mutually exclusive flags witch have their own options. Lets say, if I invoke the "stop_service" flag, I want a "name" option; but if I invoke the "send_report" flag I want a "email" option. For parsing that I use "Getopt::Long". This is the code:
use Getopt::Long;
# Option vars
my $stop_service; # flag
my $send_report; # flag
my $name; # string
my $email; # string
# Get all possible options
GetOptions(
# Flag and options for stop_service
"stop_service" => \$stop_service, # Mutual Exclusion Flag
"name=s" => \$name, # option string
# Flag and options for send_report
"send_report" => \$send_report, # Mutual Exclusion Flag
"email=s" => \$email, # option string
);
# Parsing correct combinations
# --stop_service --name XXX
if (($stop_service and !$send_report) # mutual exclusion
and ($name && !$email)) # options
{
print "stop_service + name: \n";
print $stop_service, " - ", $name, "\n";
}
# --send_report --email XXX
elsif ((!$stop_service and $send_report) # mutual exclusion
and (!$name && $email)) # options
{
print "send_report + email: \n";
print $send_report, " - ", $email, "\n";
}
# HELP
else {
print <<DOC;
Help in line 1.
Help in line 2.
DOC
}
It works well:
[getopt]$ perl 06_getopt_cond_3.pl --stop_service --name jumersindo
stop_service + name:
1 - jumersindo
[getopt]$ perl 06_getopt_cond_3.pl --send_report --email [email protected]
send_report + email:
1 - [email protected]
[getopt]$ perl 06_getopt_cond_3.pl --send_report --name
Option name requires an argument
Help in line 1.
Help in line 2.
Are there a more "automatic" way of configuring that? or I need to specify all the option combinations with the "if" sentences?
Upvotes: 1
Views: 161
Reputation: 2077
Based on Avoiding mix of certain arguments to script, I managed to implement this solution. The idea is only accept the explicitly specified options and reject other combinations, like that:
use strict;
use Getopt::Long;
# Option vars
my %options= ();
# Get all possible options
GetOptions(
# Mutually exclusive flags
"detener_servicio|stop_service" => \$options{stop_service},
"arrancar_servicio|start_service" => \$options{start_service},
"reiniciar_servicio|restart_service" => \$options{restart_service},
"registrar_servicio|record_service" => \$options{record_service},
"enviar_informe|send_report" => \$options{send_report},
# Options
"nombre|name=s" => \$options{name},
"script=s" => \$options{script},
"ruta|path=s" => \$options{path},
"ejecutables|execs=s" => \$options{execs},
"email=s" => \$options{email},
);
if (only_specified_options(\%options, 'stop_service', 'name')) {
print "Stoping service: ", $options{name}, "\n";
}
elsif (only_specified_options(\%options, 'start_service', 'name')) {
print "Starting service: ", $options{name}, "\n";
}
elsif (only_specified_options(\%options, 'restart_service', 'name')) {
print "Restarting service: ", $options{name}, "\n";
}
elsif (only_specified_options(\%options, 'record_service', 'name',
'script','path','execs')) {
print "Recording service: ", $options{name}, " ",
$options{script}, " ",
$options{path}, " ",
$options{execs} , " ", "\n";
}
elsif (only_specified_options(\%options, 'send_report', 'email')) {
print "Sending report: ", $options{email}, "\n";
}
else {
print <<DOC;
Usage:
script --stop_service --name <NAME>
script --start_service --name <NAME>
script --restart_service --name <NAME>
script --record_service --name <NAME> --script <SCRIPT>
--path <PATH> --execs <EXECS>
script --send_report --email <EMAIL>
DOC
}
# only_specified_options(\%options, 'option_1', 'option_2',..., 'option_n')
# If only specified options are present => return true
# otherwise => false
sub only_specified_options {
my $opt_ref = shift;
my %must_params = map { $_ => 1 } @_;
my $result_bool = 1;
while ((my $key, my $value) = each (%$opt_ref)) {
$result_bool &&= (exists($must_params{$key})?$value:!$value);
}
return $result_bool;
}
Upvotes: 2