Parse command-line arguments
Command-line arguments can be quite complicated, as in "nc -v -n -z -w 1 192.168.1.2 1-1000". Many languages provide a library (getopt or GetOpt) to parse the raw command line options in an intelligent way.
Bracmat
Per default, Bracmat treats all arguments as expressions and parses and evaluates them from left to right. A call to the function arg$
pops the next argument from the list of arguments and returns it as an inert string in no need of further parsing and evaluation.
bracmat arg$:?a 123 arg$:?b 77 !a+!b:?c out$!c
Output:
200
C
The man page for getopt (man 3 getopt) provides better option handling with examples. But if you just want to parse one argument... (adapted from simple database task): <lang c>#include <stdio.h> int main(int argc, char **argv){
int i; char *commands[]={"-c", "-p", "-t", "-d", "-a", NULL}; enum {CREATE,PRINT,TITLE,DATE,AUTH}; if (argc<2) {
usage: printf ("Usage: %s [commands]\n"
"-c Create new entry.\n" "-p Print the latest entry.\n" "-t Sort by title.\n" "-d Sort by date.\n" "-a Sort by author.\n",argv[0]); return 0; } for (i=0;commands[i]&&strcmp(argv[1],commands[i]);i++); switch (i) { case CREATE:
...
break; case PRINT:
...
break;
... ...
default: printf ("Unknown command..." ...); goto usage; } return 0;
}</lang>
Go
Most simply, implementing the suggested example from the talk page: <lang go>package main
import (
"flag" "fmt"
)
func main() {
b := flag.Bool("b", false, "just a boolean") s := flag.String("s", "", "any ol' string") n := flag.Int("n", 0, "your lucky number") flag.Parse() fmt.Println("b:", *b) fmt.Println("s:", *s) fmt.Println("n:", *n)
}</lang> Example runs:
> parse b: false s: n: 0 > parse -s bye -b b: true s: bye n: 0 > parse -n 99 -s "say my name" b: false s: say my name n: 99
Icon and Unicon
The Icon Programming Library provides a procedure for processing command line options. See the library reference for detailed documentation. The code below is an example.
<lang Icon>link options
procedure main(ARGLIST) /errproc := stop # special error procedure or stop() opstring := "f!s:i+r.flag!string:integer+real." # example opttable := options(ARGLIST,optstring,errproc)
if \opttable[flag] then ... # test a flag r := opttable(real) # assign a real r2 := opttable(r) # assign another real s := opttable(s) # assign a string i := opttable(i) # assign an integer ... end</lang>
options.icn supports getting command-line options
J
When J starts up from the command line, the command line arguments are available in the array ARGV
. On modern machines, the first command line argument is the name of the executable (the J interpeter, in this case).
Typically, the next argument (if present) is the name of a file whose contents will be executed.
Further command line analysis might include:
- Test if an argument is present:
- <lang j> (<'-b') e. ARGV</lang>
- This is true if the argument is present and false, if it is not.
- Or, find the name of an optional file:
- <lang j> (ARGV i.<'-f') {:: ARGV,a:</lang>
- This is the name of the first file named after the first -f argument, or empty if there was no such file.
Other concepts are also possible...
Mathematica
The command line is parsed and stored into a list of strings to ease manual handling by list processing functions. <lang Mathematica> $CommandLine -> {math, -v, -n, -z, -w, 1, 192.168.1.2, 1-1000} </lang>
PicoLisp
PicoLisp doesn't have a library to get options. Instead, the command line is parsed at startup and handled in the following way: Each command line argument is executed (interpreted) as a Lisp source file, except that if the first character is a hypen '-', then that arguments is taken as a Lisp function call (without the surrounding parentheses). For example, the command line <lang shell>$ ./pil abc.l -foo def.l -"bar 3 4" -'mumble "hello"' -bye</lang> has the effect that
- The file "abc.l" is executed
- (foo) is called
- The file "def.l" is executed
- (bar 3 4) is called
- (mumble "hello") is called
- (bye) is called, resulting in program termination
Command line arguments like "-v", "-n" and "-z" can be implemented simply by defining three functions 'v', 'n' and 'z'.
In addition to the above mechanism, the command line can also be handled "manually", by either processing the list of arguments returned by 'argv', or by fetching arguments individually with 'opt'.
Ruby
Ruby's standard library provides two different packages to parse command-line arguments.
- 'getoptlong' resembles the libraries from other languages.
- 'optparse' has more features.
Ruby with 'getoptlong'
<lang ruby>#!/usr/bin/env ruby
- == Synopsis
- pargs: Phone a friend
- == Usage
- pargs [OPTIONS]
- --help, -h:
- show usage
- --eddy, -e <message>
- call eddy
- --danial, -d <message>
- call daniel
- --test, -t
- run unit tests
require "getoptlong" require "rdoc/usage"
def phone(name, message) puts "Calling #{name}..." puts message end
def test phone("Barry", "Hi!") phone("Cindy", "Hello!") end
def main mode = :usage
name = "" message = ""
opts=GetoptLong.new( ["--help", "-h", GetoptLong::NO_ARGUMENT], ["--eddy", "-e", GetoptLong::REQUIRED_ARGUMENT], ["--daniel", "-d", GetoptLong::REQUIRED_ARGUMENT], ["--test", "-t", GetoptLong::NO_ARGUMENT] )
opts.each { |option, value| case option when "--help" RDoc::usage("Usage") when "--eddy" mode = :call name = "eddy" message = value when "--daniel" mode = :call name = "daniel" message = value when "--test" mode = :test end }
case mode when :usage RDoc::usage("Usage") when :call phone(name, message) when :test test end end
if __FILE__==$0 begin main rescue Interrupt => e nil end end</lang>
$ ./pargs.rb -h Usage ----- pargs [OPTIONS] --help, -h: show usage --eddy, -e <message> call eddy --daniel, -d <message> call daniel --test, -t run unit tests $ ./pargs.rb -e Yo! Calling eddy... Yo! $ ./pargs.rb --test Calling Barry... Hi! Calling Cindy... Hello!
Ruby with 'optparse'
<lang ruby>require 'optparse'
sflag = false longflag = false count = 0 percent = 50 fruit = nil
OptionParser.new do |opts|
# Default banner is "Usage: #{opts.program_name} [options]". opts.banner += " [arguments...]" opts.separator "This demo prints the results of parsing the options." opts.version = "0.0.1"
opts.on("-s", "Enable short flag") {sflag = true} opts.on("--long", "Enable long flag") {longflag = true} opts.on("-b", "--both", "Enable both -s and --long" ) {sflag = true; longflag = true} opts.on("-c", "--count", "Add 1 to count") {count += 1}
# Argument must match a regular expression. opts.on("-p", "--percent PERCENT", /[0-9]+%?/i, "Percent [50%]") {|arg| percent = arg.to_i}
# Argument must match a list of symbols. opts.on("-f", "--fruit FRUIT", [:apple, :banana, :orange, :pear], "Fruit (apple, banana, orange, pear)" ) {|arg| fruit = arg}
begin # Parse and remove options from ARGV. opts.parse! rescue OptionParser::ParseError => error # Without this rescue, Ruby would print the stack trace # of the error. Instead, we want to show the error message, # suggest -h or --help, and exit 1.
$stderr.puts error $stderr.puts "(-h or --help will show valid options)" exit 1 end
end
print <<EOF Short flag: #{sflag} Long flag: #{longflag} Count: #{count} Percent: #{percent}% Fruit: #{fruit} Arguments: #{ARGV.inspect} EOF</lang>
$ ruby takeopts.rb -h Usage: takeopts [options] [arguments...] This demo prints the results of parsing the options. -s Enable short flag --long Enable long flag -b, --both Enable both -s and --long -c, --count Add 1 to count -p, --percent PERCENT Percent [50%] -f, --fruit FRUIT Fruit (apple, banana, orange, pear) $ ruby takeopts.rb -v takeopts 0.0.1 $ ruby takeopts.rb -b -c Short flag: true Long flag: true Count: 1 Percent: 50% Fruit: Arguments: [] $ ruby takeopts.rb -ccccp90% -f oran -- -arg Short flag: false Long flag: false Count: 4 Percent: 90% Fruit: orange Arguments: ["-arg"]
Tcl
The following proc detects and removes argument-less (-b) and one-argument options from the argument vector. <lang Tcl>
proc getopt {_argv name {_var ""} {default ""}} { upvar 1 $_argv argv $_var var set pos [lsearch -regexp $argv ^$name] if {$pos>=0} { set to $pos if {$_var ne ""} {set var [lindex $argv [incr to]]} set argv [lreplace $argv $pos $to] return 1 } else { if {[llength [info level 0]] == 5} {set var $default} return 0 } }
</lang> Usage examples:
getopt argv -sep sep ";" ;# possibly override default with user preference set verbose [getopt argv -v] ;# boolean flag, no trailing word
Searching with -regexp allows to specify longer mnemonic names, so it still succeeds on longer flags, e.g.
$ myscript.tcl -separator '\t' ...