Read optional command-line arguments in Perl

2019-07-23 04:52发布

问题:

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?

回答1:

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



回答2:

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.