ESN 14339-080107-605240-85


Document Name: Perl Getopt and GetOptions
Document Description: ./Unix/perlgetopts.html

Perl Getopt and GetOptions

Two Perl modules (Getopt and Getoptions::Long) work to extract program flags and arguments much like Getopt and Getopts do for shell programming. The Perl modules, especially GetOptions::Long, are much more powerful and flexible.

Simple scripts show the power of these:

 #!/usr/bin/perl
 # script is "./g"
 use Getopt::Std;
 %options=();
 getopts("od:fF",\%options);
 # like the shell getopt, "d:" means d takes an argument
 print "-o $options{o}\n" if defined $options{o};
 print "-d $options{d}\n" if defined $options{d};
 print "-f $options{f}\n" if defined $options{f};
 print "-F $options{F}\n" if defined $options{F};
 print "Unprocessed by Getopt::Std:\n" if $ARGV[0];
 foreach (@ARGV) {
   print "$_\n";
 }
 
 

Trying it out:

 bash-2.05a$ ./g  -f -d F -o -F
 -o 1
 -d F
 -f 1
 -F 1
 bash-2.05a$ ./g -o -d foo
 -o 1
 -d foo
 bash-2.05a$ ./g -o rough -d foo
 -o 1
 Unprocessed by Getopt::Std:
 rough
 -d
 foo
 

Processing of arguments stops when it saw "rough".

If you leave off a required argument, it just gets swallowed:

 bash-2.05a$ ./g -d
 bash-2.05a$ ./g -d foo
 -d foo
 

But it's easily confused:

 bash-2.05a$ ./g -d -o -f       
 -d -o
 -f 1
 

It thinks that -o is the argument of -d.

 bash-2.05a$ ./g -k    
 Unknown option: k
 

Like the simple shell "getopt", this complains when it gets an option that it doesn't know about. Unlike the shell "getopt", prefacing the option string with a ":" doesn't help. Instead, use "getopt":

 #!/usr/bin/perl
 # we'll call this one ./gg
 use Getopt::Std;
 %options=();
 getopt("odfF",\%options);
 print "-o $options{o}\n" if defined $options{o};
 print "-d $options{d}\n" if defined $options{d};
 print "-f $options{f}\n" if defined $options{f};
 print "-F $options{F}\n" if defined $options{F};
 

Note the lack of any ":". This module doesn't care which flags take values and which don't: it assumes ALL of them take arguments.

The "getopt" isn't very bright:

 bash-2.05a$ ./gg -f -o -d foo 
 -d foo
 -f -o
 bash-2.05a$ ./g -f -o -d foo 
 -o 1
 -d foo
 -f 1
 

But it doesn't complain:

 bash-2.05a$ ./gg -l
 bash-2.05a$ ./g -l
 Unknown option: l
 
 

Unlike their shell cousins, neither of these have any issues with arguments containing spaces:

 
 bash-2.05a$ ./g -o  -d "foo bar"          
 -o 1
 -d foo bar
 bash-2.05a$ ./gg -o "foo"  -d "foo bar" 
 -o foo
 -d foo bar
 

Far better than either of these is the Getopt::Long module. Here's a script to play with it:

 #!/usr/bin/perl
 use Getopt::Long;
 GetOptions("o"=>\$oflag,
             "verbose!"=>\$verboseornoverbose,
             "string=s"=>\$stringmandatory,
             "optional:s",\$optionalstring,
             "int=i"=> \$mandatoryinteger,
             "optint:i"=> \$optionalinteger,
             "float=f"=> \$mandatoryfloat,
             "optfloat:f"=> \$optionalfloat);
 print "oflag $oflag\n" if $oflag;
 print "verboseornoverbose $verboseornoverbose\n" if $verboseornoverbose;
 print "stringmandatory $stringmandatory\n" if $stringmandatory;
 print "optionalstring $optionalstring\n" if $optionalstring;
 print "mandatoryinteger $mandatoryinteger\n" if $mandatoryinteger;
 print "optionalinteger $optionalinteger\n" if $optionalinteger;
 print "mandatoryfloat $mandatoryfloat\n" if $mandatoryfloat;
 print "optionalfloat $optionalfloat\n" if $optionalfloat;
 
 print "Unprocessed by Getopt::Long\n" if $ARGV[0];
 foreach (@ARGV) {
   print "$_\n";
 }
 

The hash array that this uses holds the argument name and the type of argument; what that points to is where it will store values for options processed.

Playing with it:

 #
 # doesn't care if it's -o or --o
 bash-2.05a$ ./ggg -o
 oflag 1
 bash-2.05a$ ./ggg --o
 oflag 1
 #
 # abbreviating is ok too
 bash-2.05a$ ./ggg -verbose
 verboseornoverbose 1
 bash-2.05a$ ./ggg -verb   
 verboseornoverbose 1
 #
 # but not this
 bash-2.05a$ ./ggg -verbosity 
 Unknown option: verbosity
 #
 # $verboseonoverbose will be 0 here
 bash-2.05a$ ./ggg -noverb
 #
 # strings
 bash-2.05a$ ./gggg -s    
 Option string requires an argument
 bash-2.05a$ ./ggg -s=foo
 stringmandatory foo
 bash-2.05a$ ./ggg -optional
 bash-2.05a$ ./ggg -optional=foo
 optionalstring foo
 #
 # ambiguity
 bash-2.05a$ ./ggg --opt     
 Option opt is ambiguous (optfloat, optint, optional)
 #
 # floats and integers
 bash-2.05a$ ./ggg --optfloat=75.6
 optionalfloat 75.6
 bash-2.05a$ ./ggg --optint=75.6
 Value "75.6" invalid for option optint (number expected)
 bash-2.05a$ ./ggg --optint=75  
 optionalinteger 75
 bash-2.05a$ ./ggg -f --optfloat=75.6 -o
 Value "--optfloat=75.6" invalid for option float (real number expected)
 oflag 1
 # once it runs out of options, it leaves @ARGV alone:
 bash-2.05a$ ./ggg -o foo bar
 oflag 1
 
 Unprocessed by Getopt::Long
 foo
 bar
 
 

GetOpt::Long is obviously much more flexible. The hash you pass is a little clumsy, but if you think about it, there's no better way to do it. In some places, you might use something like this:

 #!/usr/bin/perl
 use Getopt::Long;
 my %moo=();
 GetOptions("o"=>\$moo{$oflag},
             "verbose!"=>\$moo{verbose},
             "string=s"=>\$moo{stringmandatory},
             "optional:s"=>\$moo{optionalstring},
             "int=i"=> \$moo{mandatoryinteger},
             "optint:i"=> \$moo{optionalinteger},
             "float=f"=> \$moo{mandatoryfloat},
             "optfloat:f"=> \$moo{optionalfloat});
 
 foreach (keys %moo) {
  print "$_ = $moo{$_}\n";
 }
 
 print "Unprocessed by Getopt::Long\n" if $ARGV[0];
 foreach (@ARGV) {
   print "$_\n";
 }
 

but if you have so many flags that you are thinking that is helpful, your program is surely trying much too hard to be all things to all people.


Author: Anthony Lawrence - Contact Author
Publisher: Anthony Lawrence
Licensee Name: Anthony Lawrence
Reference URL: http://aplawrence.com/Unix/perlgetopts.html
Copyright: All Rights Reserved
Registration Date: 1/7/2008 8:53:10 PM UTC
Views: 161055




NUMLY.COM