|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
Old News
|
Recommended Books | Recommended Links | Getopt::Long |
|
The option -s of Perl interpreter provides Perl programmers a rudimentary way to pass command line options – it will take options from the command line and set them as Perl variables with the same name (for example, -h becomes $h ). However, it had a few limitations:
|
The Getopt::Long and Getopt::Std modules provide pre-cooked code to solve the problem of accepting options in the program. They supports a classic Unix style of specifying options that is adequate for most programs.
Getopt::Std is limited to single letter option that can have values. It supports clustered options like in tar -cvf .
getopt()
removes the options from @ARGV
and parses them. It takes the two arguments:
Here is an example of usage:
use Getopt::Std;
my %options;
$major_version=1; $minor_version=0;
getopts("vhc:",\%options);
if ($options{'v'}) {
print "$0, version $major_version.$minor_version\n";
exit;
} elsif ($options{h}) {
print <<EOF;
$0: Example program
Syntax: $0 [-h|-v|-c <config_file>]
-h : This help message
-v : Print version on standard output and exit
-c : Specify location of config file
EOF
exit;
} elsif ($options{l}) {
if (exist $options{'c'}) {
if (-e $options{'c'}) {
print "Using configration from the $options{'c'}\n";
} else {
die "$0: specified configuration file $options{'c'} does not exists";
}
}open (SYSCONFIG, "<$options{'c'});
while (<SYSCONFIG>) {
chomp;
($param,$value)=split(/\=/,$_);
$option{$param}=$value;
}... ... ...
If we follow a letter with a colon, we expect that a value will be stored in the hash. If we don't use a colon, then the hash value stored is just true or false depending on whether or not the option was given.
|
Switchboard | ||||
Latest | |||||
Past week | |||||
Past month |
Programs need input, and for many programs, input begins on the command line. For example, a program to print files might be invoked aspr -l -n -a 10:00 foo barpr
is the name of the program; it is followed here by six arguments. The arguments are of two sorts: options and file names.
-l
,-n
, and-a 10:00
are options. They control the manner in which the program executes. In this case,-l
tellspr
to print in landscape orientation,-n
tells it to print page numbers, and-a 10:00
tells it to print after 10:00. Options are sometimes called options or switches.foo
andbar
are file names.pr
will read these files to obtain the actual text to print.Parsing the Command Line
In Perl, command line arguments are made available to the program in the global@ARGV
array. This happens automatically: you don't have to declare anything or do anything to get them. If you wrotepr
in Perl and entered the command line shown above, then at the beginning of program execution@ARGV
would have six elements:$ARGV[0] '-l' $ARGV[1] '-n' $ARGV[2] '-a' $ARGV[3] '10:00' $ARGV[4] 'foo' $ARGV[5] 'bar'Now the fun starts. Given@ARGV
as shown, the program has to identify-l
,-n
, and-a
as options, associate10:00
with-a
, and identifyfoo
andbar
as file names. This is called parsing the command line.Easy to be Hard.
Parsing the command line is a problem. The problem isn't that it is so hard, but rather that it is so easy: for many programs, it can be done in under 20 lines of code. Because parsing the command line seems easy, it is often not identified as a distinct function of the program. It never gets a functional specification, or a design, or even the considered attention of the programmer. This leads to many bad things:
- Design by accretion. As the program evolves, parsing features are added on an ad-hoc basis.
- Open code. The command line is parsed in open code, scattered across the program. The parsing code isn't contained in any subroutine, module, or class.
- Non-standard interfaces. Different programs are liable to parse the command line in slightly different ways. This confuses users.
- Sub-standard interfaces. Programmers tend to implement only what they need-or think they need. Features such as switch clustering, abbreviations, and help text, for example, may be omitted.
- Bugs. When every program has its own parsing code, every program can have its own parsing bugs.
- Duplication. You keep writing that same 50 lines of code, over and over again, in every program.
The Eightfold Path
In Perl, there is a better way. In fact, there are many better ways. In 00modlist.long.html, we findGetopt::Declare An easy-to-use WYSIWYG command-line parser Getopt::EvaP Long/short options, multilevel help Getopt::Long Advanced option handling Getopt::Mixed Supports both long and short options Getopt::Regex Option handling using regular expressions Getopt::Simple A simplified interface to Getopt::Long Getopt::Std Implements basic getopt and getopts Getopt::Tabular Table-driven argument parsing with help textEach of these is a Perl module for parsing the command line. They have been designed, written, debugged, and encapsulated. You don't have to write them again. They support standard interfaces.If the list above seems daunting, start with
Getopt::Std
Getopt::Std
.Getopt::Std
supports a good, simple command line style that is adequate for many programs. It automatically handles options given in any of these forms:pr -l -n -a 10:30 foo bar pr -lna 10:30 foo bar pr -lna10:30 foo barTo useGetopt::Std
, writeuse Getopt::Std; my %Options; getopt('a', \%Options);Getopt::Std
exports thegetopt()
routine.getopt()
takes two parameters: a string and a hash reference. The string lists all the options that take arguments. The hash receives the options found on the command line.
getopt()
removes the options from@ARGV
and parses them. Upon return, each option appears as a hash key in%Options
. For each key, the hash value is the argument of the option if it takes one, and1
if it does not. Finally, any file names that follow the options are left in@ARGV
for the program to process. For any of the command lines shown above,getopt()
would set%Options
and@ARGV
to%Options = (l => 1, n => 1, a => '10:30') @ARGV = qw(foo bar)Getopt::Std
also has another interface:$ok = getopts('a:ln', \%Options);Likegetopt()
,getopts()
takes a string and a hash reference. The string includes all the option letters: both those that take arguments and those that do not. Option letters that take an argument are marked with a trailing colon. Becausegetopts()
has a list of all the valid options, it can do some simple error checking:getopts()
returns false if there are invalid options on the command line, and true otherwise.If you need more power that
Getopt::Long
Getopt::Std
provides, consider usingGetopt::Long
. The name::Long
refers to an option style that uses two dashes and the complete option name, rather than a single character:pr --landscape --numbers --after 10:30 foo barHowever,Getopt::Long
is not merelyGetopt::Std
with a facelift. It provides a large-some would say bewildering-assortment of facilities for parsing the command line in different ways. In addition,Getopt::Long
has evolved over the last ten years, reflecting changes in the underlying Perl language, changes in programming style, and changes in interface style. At the same time, it maintains backward compatibility with previous versions.All this makes the programming interface to
Getopt::Long
large and complex. For a complete description, you should read the documentation that is contained within the module itself. Here, I'll give just a brief survey, illustrating the simpler features, and reflecting current style.Basic Facilities
Conceptually, the interface toGetopt::Long
is similar to that ofGetopt::Std
. It exports a routine namedGetOptions()
.GetOptions()
takes a series of option specifiers, which tell it how to parse the command line, and a hash reference, where it stores the results. It returns true if there are no errors.$ok = GetOptions(\%Options, "landscape", "numbers!", "after=s");Each option specifier gives the name of an option, possibly followed by an argument specifier. The name will become a hash key. The argument specifier tells how to parse the argument to that option.In the example above,
landscape
has no argument specifier. This means that it takes no argument, and$Options{landscape}
will be1
or0
according as--landscape
does or does not appear on the command line.numbers!
also takes no argument, but the!
means that it may be explicitly negated by prefixing it withno
on the command line:pr --nonumbersafter=s
takes a string argument; the argument will become the value of$Options{after}
.after:s
also takes a string argument, but the colon means that the argument is optional. Other argument specifiers are=i
for integer arguments and=f
for floating point arguments.A double dash on the command line terminates the option list.
Hairy Stuff
If an argument specifier is suffixed with an@
, then the option may be given multiple times on the command line, and the corresponding value in%Options
becomes a reference to an array containing all the values supplied for that option. For example:GetOptions(\%Options, "x=f@", "y=f@")will parsegraph --x 1 --x 2 --x 3 --y 1 --y 4 --y 9resulting in%Options = (x => [1, 2, 3], y => [1, 4, 9])Similarly, if an argument specifier is suffixed with a%
, then the option takes key=value pairs, and the corresponding value in%Options
becomes a reference to a hash of those pairs. SoGetOptions(\%Options, "define=s%")will parse Stroustrup's examplecc --define sqrt=rand --define exit=abort hello.ccresulting in%Options = (define => { sqrt => 'rand', exit => 'abort' })The Kitchen Sink
The empty string is a valid option. It is written on the command line as a single dash, and results in the null key being entered into%Options
with a value of1
. This form is conventionally used to specify that the program should take input fromSTDIN
, rather than from a named file:cat -You don't have to store all the options in%Options
. Each option can have its own linkage specification, which may be a scalar ref, an array ref, a hash ref, or a code ref. For scalar, array, and hash refs, the option is stored in the referenced variable. If the linkage specification is a code ref, the option isn't stored anywhere; instead, the option name and value are passed to the referenced subroutine.Option names can have aliases, and can be abbreviated to uniqueness. You can configure
Getopt::Long
for compatibility with GNU, or POSIX. You can control case sensitivity. You can cluster options. You can pass options through to called programs. You can intersperse options and non-option arguments on the command line. This allows different files to be processed with different options:pr --numbers foo --nonumbers barFinally, you can specify a code ref to process arguments that aren't options. This allowsGetOptions()
to process the entire command line, and potentially reduces your program to a singleGetOptions(...);call, plus subroutines.The Rest of the Pack
Getopt::Std
andGetopt::Long
are both supplied with the standard Perl distribution. There are currently six otherGetopt::
modules available on CPAN. Here is a quick tour.
Getopt::Simple
Getopt::Simple
describes itself as a simple wrapper aroundGetopt::Long
. However, nothing that supports the functionality ofGetopt::Long
can be entirely simple. In fact,Getopt::Simple
is an object-oriented wrapper aroundGetopt::Long
. Rather than coding option descriptions into strings,Getopt::Simple
lays them out in hash tables:$descriptions = { landscape => { type => '' }, numbers => { type => '' }, after => { type => '=s' } }getOptions()
is invoked as a method on aGetopt::Simple
object:$options = new Getopt::Simple; $options->getOptions($descriptions, "Usage: pr -landscape -numbers -after time");and options are retrieved through the $options object:$option->{switch}{landscape} and ... $option->{switch}{after } and ...
Getopt::Tabular
Getopt::Tabular
uses a table to describe options, and then parses the command line through a procedural interface:@options = (['-landscape', 'boolean', 0, \$landscape', 'print in landscape orientation'], ['-numbers' , 'boolean', 0, \$numbers' , 'print page numbers' ], ['-after' , 'string' , 1, \$time' , 'print after time' ], ); GetOptions(\@options, \@ARGV) or exit 1;Each line in the table describes a single option, and specifies the option name, type, number of arguments, action to take, and help text. The simplest action is to set a scalar;Getopt::Tabular
can also collect arguments from the command line and assign them to an array, or pass them to a subroutine.If anything goes wrong,
GetOptions()
automatically formats an error message, based on the help text supplied in@options
.Getopt::Tabular
also supplies an entry point calledSpoofGetOptions()
.SpoofGetOptions(\@options, \@ARGV)parses the command line and checks it for errors, but doesn't take any action. This is particularly useful for programs that use subroutines to process arguments, because subroutines can do expensive or irreversible things.
Getopt::Mixed
Getopt::Mixed
supports both long and short options: long because they are easy to remember; short because they are easy to type. Long options are introduced on the command line with two dashes; short options with one:pr --landscape -a 12:00 foo barThe programming interface is similar toGetopt::Long
:Getopt::Mixed::getOptions(@option_descriptions)There is also an iterative form, which allows the program to process options one at a time:Getopt::Mixed::init(@option_descriptions); while (($option, $value) = Getopt::Mixed::nextOption()) { ... } Getopt::Mixed::cleanup();The results are stored in global variables. Given the command line shown above,Getopt::Mixed
would set$opt_landscape = 1 $opt_a = '12:00'Non-options arguments are left in@ARGV
.
Getopt::Declare
Getopt::Declare
doesn't parse anything directly. Rather, it builds and runs a parser. Options and their arguments are laid out in a single specification string:$spec = q(-l Print in landscape mode { $landscape = 1 } -n Print page numbers { $numbers = 1 } -a <time:s> Print after time { Queue($time) });The string describes each option, along with help text and a BLOCK to be executed when the option is found.Getopt::Declare::new
creates a parser object from a specification string:$parser = new Getopt::Declare $spec;As written, this builds a parser and runs it on the command line; with additional arguments, it can parse strings or configuration files. Options and their values can be retrieved from$parser
, but this is typically unnecessary, because the BLOCKs in the specification string contain arbitrary Perl code. There are powerful facilities for specifying and checking option syntax and arguments. Options can be required, and groups of options can be made mutually exclusive. Usage lines are automatically generated from the help text. The parser object can be saved and later run on different input.
Getopt::EvaP
Getopt::EvaP
is broadly similar toGetopt::Simple
andGetopt::Declare
. Options and help text are specified in tables. A call toEvaP()
parses the command line according to the tables and returns the results in an%Options
hash:EvaP \@option_specs, \@help_text, \%optionsPerhaps the most interesting feature ofGetopt::EvaP
is that it has been implemented for Perl, Perl/Tk, Tcl and C. If you are developing in multiple languages,EvaP
can provide a consistent user interface across all your applications.
Getopt::Regex
Getopt::Regex
takes a different approach to managing the potential complexity of command line syntax. Rather than implementing sophisticated parsing facilities of its own, it relies on the Perl regular expression engine.GetOptions(\@ARGV, [$regex, \$scalar , $takesarg], [$regex, sub {...} , $takesarg], ...);For each option, the user passes an array ref. The first element is a regular expression, the second is either a scalar ref or a code ref, and the third indicates whether the option takes an argument. An element of@ARGV
is recognized as an option if it matches a$regex
. When an option is found,GetOptions()
sets$scalar
or callssub {...}
, as appropriate. If the option takes an argument, the argument is assigned to$scalar
, or passed tosub {...}
.The Importance of Being Lazy
One of the principal virtues of a programmer is Laziness, and these modules provide a wonderful opportunity to be Lazy. Before parsing your own command line, look to see if there isn't aGetopt::
module that will do what you need. If there is, use it. If there isn't, encapsulate your parsing code in a newGetopt::
module, and consider submitting it to CPAN. Then other programmers can be Lazy, even if you can't.
This how-to comes with no guarantees other than the fact that these code segments were copy/pasted from code that I wrote and ran successfully.
Process options passed to a program using
getopts()
.Make a global hash to store the options. Use the standard Getopt module. Make a string of one-character options. A character preceeding a colon takes an argument. The getopts function takes two arguments: a string of options, and a hash reference. For each command line option (aka switch) found, getopts sets $opt{x} (where x is the switch name) to the value of the argument, or 1 if no argument was provided.
Example
# # Globals # use vars qw/ %opt /;# # Command line options processing # sub init() { use Getopt::Std; my $opt_string = 'hvdf:'; getopts( "$opt_string", \%opt ) or usage(); usage() if $opt{h}; }# # Message about this program and how to use it # sub usage() { print STDERR << "EOF";This program does...usage: $0 [-hvd] [-f file]-h : this (help) message -v : verbose output -d : print debugging messages to stderr -f file : file containing usersnames, one per lineexample: $0 -v -d -f fileEOF exit; }init();print STDERR "Verbose mode ON.\n" if $opt{v}; print STDERR "Debugging
Society
Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers : Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism : The Iron Law of Oligarchy : Libertarian Philosophy
Quotes
War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda : SE quotes : Language Design and Programming Quotes : Random IT-related quotes : Somerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose Bierce : Bernard Shaw : Mark Twain Quotes
Bulletin:
Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 : Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law
History:
Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds : Larry Wall : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOS : Programming Languages History : PL/1 : Simula 67 : C : History of GCC development : Scripting Languages : Perl history : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history
Classic books:
The Peter Principle : Parkinson Law : 1984 : The Mythical Man-Month : How to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor
The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D
Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.
This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...
|
You can use PayPal to to buy a cup of coffee for authors of this site |
Disclaimer:
The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.
Last modified: March 12, 2019