分类:
2009-07-11 18:58:41
#!/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