I am using Getopt::Long to pass options to my Perl script.
But I want to do something like this :
perl myScript mandatoryArgument1 -optionalArgument1=someValue
I want the script to throw an error if mandatoryArgument1 is missing. How can this be done?
The good Getopt::Long
does not have a mechanism for that. It specifically processes options.
However, as it does its work it removes those options from @ARGV
so once it's finished you can check whether the expected arguments are there. See the second part for this but I would like to first suggest another way: Make those arguments named and then Getopt
will process them.
Then it is easy to check whether they were submitted. For example
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
my $mandatoryArg;
my $opt;
# Read command-line arguments, exit with usage message in case of error
GetOptions( 'name=s' => \$mandatoryArg, 'flag' => \$opt )
or usage();
if (not defined $mandatoryArg) {
say STDERR "Argument 'name' is mandatory";
usage();
}
# The program goes now. Value for $opt may or may have not been supplied
sub usage {
say STDERR "Usage: $0 ..."; # full usage message
exit;
}
So if --name string
isn't given on the command line the $mandatoryArg
stays undefined and the program exits. That variable doesn't need a default value since it is mandatory, and it shouldn't have one for this check to work.
Argument checking and processing is often far more involved, and this is when Getopt
shines.
The mandatoryArgument1
in the question is supplied without a name. While Getopt
can be made to act on a non-option input, it cannot detect that an expected one is not there.†
The module does allow to mix arguments with named options, anywhere on the command line. See Option with other arguments in docs. So you can invoke the program as
script.pl --opt1 value1 unnamed_arg --opt2 value2
but I'd suggest to the user to supply them after named options.
Then, after GetOptions
does its job, @ARGV
will contain the string unnamed_arg
and you can get it (or find out that it isn't there). Processing of named options by GetOptions
is the same as above.
my ($var1, $var2, $flag);
GetOptions('opt1=s' => \$var1, 'opt2=i' => \$var2, 'f' => \$flag)
or usage();
# All supplied named options have been collected, all else left in @ARGV
# Read the remaining argument(s) from @ARGV, or exit with message
# This can get far more complicated if more than one is expected
my $mandatoryArg1 = shift @ARGV || do {
say STDERR "Mandatory argument (description) is missing";
usage();
};
Above you have to process @ARGV
by hand once Getopt
picked up the named arguments.
If there is more than one such argument the user has to strictly respect their expected relative position on the command line, as there is in general no way for the program to tell what's what. So errors where the user confuses their order on the command line in general cannot be caught.
This becomes a hindrance and I'd suggest to have at most one kind of unnamed argument(s), and only in the case where it is obvious what that must be, like filename(s).
While all this is possible modules like Getopt
exist precisely so that we don't have to do it.
† Action for input that doesn't look like an option is set up using the "name" of '<>'
Getoptions( 'opt=s' => \$var, ..., '<>' => \&arg_cb );
sub arg_cb { say "Doesn't look like an option: $_[0]" }
where the sub arg_cb
is invoked only if a non-option-looking argument is seen.