make Versus Ant
2.6 Parsing Command-Line Arguments
Problem
You need to parse command-line options. Java doesn’t provide an API for it.
Solution
Look in theargs array passed as an argument tomain. Or use myGetOpt class.
Discussion
The Unix folk have had to deal with this longer than anybody, and they came up with a C-library function calledgetopt.*getoptprocesses your command-line ments and looks for single-character options set off with dashes and optional argu-ments. For example, the command:
sort -n -o outfile myfile1 yourfile2
runs the standard sort program. The -ntells it that the records are numeric rather than textual, and the-o outfiletells it to write its output into a file named outfile.
The remaining words, myfile1 and yourfile2, are treated as the input files to be sorted. On Windows, command arguments are sometimes set off with slashes ( / ).
We use the Unix form—a dash—in our API, but feel free to change the code to use slashes.
* The Unix world has several variations ongetopt; mine emulates the original AT&T version fairly closely, with some frills such as long-name arguments.
EachGetOpt parser is constructed to recognize a particular set of arguments; this is sensible since a given program normally has a fixed set of arguments that it accepts.
You can construct an array ofGetOptDescobjects that represent the allowable argu-ments. For the sort program shown previously, you might use:
GetOptDesc options[] = {
new GetOptDesc('n', "numeric", false}, new GetOptDesc('o', "output-file", true), });
The simple way of usingGetOpt is to call itsparseArguments method.
For backward compatibility with people who learned to use the Unix version in C, thegetopt( )method can be used normally in awhileloop. It returns once for each valid option found, returning the value of the character that was found or the con-stantDONE when all options (if any) have been processed.
Here is a complete program that uses myGetOptclass just to see if there is a-h(for help) argument on the command line:
import com.darwinsys.util.GetOpt;
/** Trivial demonstration of GetOpt. If -h present, print help.
*/
public class GetOptSimple {
public static void main(String[] args) { GetOpt go = new GetOpt("h");
static void helpAndExit(int returnValue) {
System.err.println("This would tell you how to use this program");
System.exit(returnValue);
} }
Parsing Command-Line Arguments | 45 This longer demo program has several options:
import com.darwinsys.lang.GetOpt;
import com.darwinsys.lang.GetOptDesc;
import java.util.*;
/** Demonstrate the modern way of using GetOpt. This allows a subset of * <pre>Unix sort options: sort -n -o outfile infile1 infile2</pre>
* which means: sort numerically (-n), writing to file "outfile" (-o * outfile), sort from infile1 and infile2.
*/
public class GetOptDemoNew {
public static void main(String[] argv) { boolean numeric_option = false;
Map optionsFound = parser.parseArguments(argv);
Iterator it = optionsFound.keySet( ).iterator( );
}
System.out.println( );
} }}
If we invoke it several times with different options, including both single-argument and long-name options, here’s how it behaves:
> java GetOptDemoNew
Options: Numeric: false Output: null; Inputs:
> java GetOptDemoNew -M
Options: Numeric: false Output: null; Inputs: -M
> java GetOptDemoNew -n a b c
Options: Numeric: true Output: null; Inputs: a b c
> java GetOptDemoNew -numeric a b c
Options: Numeric: true Output: null; Inputs: a b c
> java GetOptDemoNew -numeric -output-file /tmp/foo a b c Options: Numeric: true Output: /tmp/foo; Inputs: a b c
A longer example exercising all the ins and outs of this version of GetOpt can be found in the online source under darwinsys/src/regress.The source code for GetOpt itself is shown in Example 2-2.
Example 2-2. Source code for GetOpt package com.darwinsys.lang;
/** A class to implement Unix-style (single-character) command-line argument * parsing. Originally patterned after (but not using code from) the Unix * getopt(3) program, this has been redesigned to be more Java-friendly.
* <p>
* This is <em>not</em> threadsafe; it is expected to be used only from main( ).
* <p>
* For another way of dealing with command lines, see the
* <a href="http://jakarta.apache.org/commons/cli/">Jakarta Commons * Command Line Interface</a>.
* @author Ian F. Darwin, [email protected]
* @version $Id: ch02,v 1.4 2004/05/04 20:11:12 ian Exp $ */
public class GetOpt {
/** The list of file names found after args */
protected List fileNameArguments;
/** The set of characters to look for */
protected GetOptDesc[] options;
/** Where we are in the options */
protected int optind = 0;
/** Public constant for "no more options" */
public static final int DONE = 0;
Parsing Command-Line Arguments | 47 /** Internal flag - whether we are done all the options */
protected boolean done = false;
/** The current option argument. */
protected String optarg;
/** Retrieve the current option argument */
public String optarg( ) { return optarg;
}
/* Construct a GetOpt parser, given the option specifications
* in an array of GetOptDesc objects. This is the preferred constructor.
*/
public GetOpt(GetOptDesc[] options) { this.options = options;
}
/* Construct a GetOpt parser, storing the set of option characters.
* This is a legacy constructor for backward compatibility.
*/
Example 2-2. Source code for GetOpt (continued)
/** Array used to convert a char to a String */
private static char[] strConvArray = { 0 };
/**
* Modern way of using GetOpt: call this once and get all options.
* <p>
* This parses the options and returns a Map whose keys are the found options.
* Normally followed by a call to getFilenameList( ).
* @return a Map whose keys are Strings of length 1 (containing the char * from the option that was matched) and whose value is a String * containing the value, or null for a non-option argument.
*/
public Map parseArguments(String[] argv) { Map optionsAndValues = new HashMap( );
/** Get the list of filename-like arguments after options */
public List getFilenameList( ) {
* returns one argument; call repeatedly until it returns DONE.
*/
Example 2-2. Source code for GetOpt (continued)
Parsing Command-Line Arguments | 49
See Also
GetOptis an adequate tool for processing command-line options. You may come up with something better and contribute it to the Java world; this is left as an exercise for the reader.
For another way of dealing with command lines, see the Jakarta Commons Com-mand Line Interface, which can be found at http://jakarta.apache.org/commons/cli/.
return DONE;
Example 2-2. Source code for GetOpt (continued)
Chapter 3ab