Hai’s Blog

September 13, 2009

Parse Command Line in a Tcl Script

Filed under: Programming, Tcl — Hai @ 4:14 pm

The Problem

I am writing script in Tcl, but want an easy and simple way to parse command line parameter. For example, the user might invoke my script as:

	tclsh myscript.tcl -server testserver15 -user testuser3

The Solution

This is one way to solve the problem. It does not mean to be the only one, but an easy and simple one. The solution is to use a library package called cmdline which comes with most Tcl installations. Below is a sample script I wrote to demonstrate this technique.

The Sample Script

To demonstrate the solution, I created a sample script called parse_argv.tcl with the following contents:

package require cmdline

# Show argv before processing
puts "Before, argv = '$argv'"

# Process the command line
set parameters {
    {server.arg ""   "Which server to test"}
    {port.arg   5551 "Port to send test cmd"}
    {user.arg   ""   "Login name"}
    {debug           "Output extra debug info"}
}
array set arg [cmdline::getoptions argv $parameters]

# Verify required parameters
set requiredParameters {server user}
foreach parameter $requiredParameters {
    if {$arg($parameter) == ""} {
        puts stderr "Missing required parameter: -$parameter"
        exit 1
    }
}

# Displays the arguments
puts ""
parray arg
puts ""

# Show argv after processing
puts "After, argv = '$argv'"

Explanation

  • Line 7 – Define the command line parameters and their defaults. If a parameter has an .arg suffix, then it must be followed by a value. A parameter without the .arg suffix is a simple boolean (0 or 1) parameter. Please note that the parameter names are case sensitive, so -server is not the same as -Server.For more information, please consult the documentation for cmdline.
  • Line 8 – A call to cmdline::getoptions does all the works. Please note:
    1. If the user supplies a parameter not that getoptions does not recognize, it will display a usage and throw an error, which will cause the script to exit prematurely.
    2. If getoptions encounters a ‘–’ (double dashes) on the command line, it will delete that token and stop processing. This behavior is consistent with many Unix’s commands.
    3. The contents of argv will be modified. That is why we pass argv instead of $argv to getoptions.
    4. getoptions returns a list of keyword/value such as {server “” port 5551 …}. The array set turns this list into an array.
  • Line 30 – After processing the command line, argv contains the left-over. Please take a look at the Sample Runs section for an example of this behavior

Sample Runs

	$ tclsh parse_argv.tcl
	Before, argv = ''
	Missing required parameter: -server

Invoke the script without specifying the required parameters will cause it to show an error then exit.


	$ tclsh parse_argv.tcl -server testserver15 -user testuser3 extra1 extra2
	Before, argv = '-server testserver15 -user testuser3 extra1 extra2'

	arg(debug)  = 0
	arg(port)   = 5551
	arg(server) = testserver15
	arg(user)   = testuser3

	After, argv = 'extra1 extra2'

In this run, the user specifies all the required parameters and a few extras. Notice:

  • How argv changed after calling getoptions
  • arg(debug) is 0 because the user has not specified a -debug flag in the command line

Conclusion

The cmdline package offers a simple and easy way to parse command line parameters. It should save programmers coding time and sanity. The package is not perfect: it does not check for required parameters, nor does it validate them. In the script, I worked around the first issue by checking for required parameters myself (lines 16 to 22).

To demonstrate the second issue, let’s take a look at the -port parameter. If I require this parameter to be an integer between 5000-5999, I have to write the verification myself.

I hope cmdline to evolve and address these issues. Meanwhile, I am glad to have it under my belt.

No Comments Yet »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.