I am new to Perl and I'm confused with its handling of optional arguments.
If I have a perl script that's invoked with something along the lines of:
plgrep [-f] < perl regular expression > < file/directory list >
How would I determine whether or not the -f
operator is given or not on the command line?
All of the parameters passed to your program appear in the array @ARGV
, so you can simply check whether any of the array elements contain the string -f
But if you are writing a program that uses many different options in combination, you may find it simpler to use the Getopt::Long
module, which allows you to specify which parameters are optional, which take values, whether there are multiple synonynms for an option etc.
A call to GetOptions
allows you to specify the parameters that your program expects, and will remove from @ARGV
any that appear in the command line, saving indicators in simple Perl variables that reflect which were provided and what values, if any, they had
For instance, in the simple case that you describe, you could write your code like this
use strict;
use warnings 'all';
use feature 'say';
use Getopt::Long;
use Data::Dump;
say "\nBefore GetOptions";
dd \@ARGV;
GetOptions( f => \my $f_option);
say "\nAfter GetOptions";
dd $f_option;
dd \@ARGV;
output
Before GetOptions
["-f", "regexp", "file"]
After GetOptions
1
["regexp", "file"]
So you can see that before the call to GetOptions
, @ARGV
contains all of the data in the command line. But afterwards, the -f
has been removed and variable $f_option
is set to 1 to indicate that the option was specified
Use Getopt::Long. You could, of course, parse @ARGV
by hand (which contains command line arguments), but there is no reason to do that with the existence of good modules for the job.
use warnings;
use strict;
use Getopt::Long;
# Set up defaults here if you wish
my ($flag, $integer, $float, $string);
usage(), exit if not GetOptions(
'f|flag!' => \$flag,
'integer:i' => \$integer,
'float:f' => \$float,
'string:s' => \$string
);
# The script now goes. Has the flag been supplied?
if (defined($flag)) { print "Got flag: $flag\n" } # it's 1
else {
# $flag variable is 'undef'
}
sub usage {
print "Usage: $0 [options]\n"; # -f or -flag, etc
}
The $flag
can simply be tested for truth as well, if that is sufficient. To only check whether -f
is there or not, need just: GetOptions('f' => \$flag); if ($flag) { };
.
The module checks whether the invocation specifies arguments as they are expected. These need not be entered, they are "options." However, for an unexpected invocation a die
or warn
message is printed (and in the above code our usage message is also printed and the script exits). So for script.pl -a
the script exits with messages (from module and sub).
Abbreviations of option names are OK, if unambiguous; script.pl -fl 0.5
exits with messages (-flag
or -float
?) while script.pl -i 5
is OK and $integer
is set to 5. On the other hand, if an integer is not supplied after -i
that is an error, since that option is defined to take one. Multiple names for options can be specified, like f|flag
. Etc. There is far more.