Приглашаем посетить
Культурология (cult-lib.ru)

Parsing Command-Line Arguments

Previous
Table of Contents
Next

Parsing Command-Line Arguments

When you are running a PHP script on the command line, you obviously can't pass arguments via $_GET and $_POST variables (the CLI has no concept of these Web protocols). Instead, you pass in arguments on the command line. Command-line arguments can be read in raw from the $argv autoglobal.

The following script:

#!/usr/bin/env php
<?php
  print_r($argv);
?>

when run as this:

> ./dump_argv.php foo bar barbara

gives the following output:

Array
(
    [0] => dump_argv.php
    [1] => foo
    [2] => bar
    [3] => barbara
)

Notice that $argv[0] is the name of the running script.

Taking configuration directly from $argv can be frustrating because it requires you to put your options in a specific order. A more robust option than parsing options by hand is to use PEAR's Console_Getopt package. Console_Getopt provides an easy interface to use to break up command-line options into an easy-to-manage array. In addition to simple parsing, Console_Getopt handles both long and short options and provides basic validation to ensure that the options passed are in the correct format.

Console_Getopt works by being given format strings for the arguments you expect. Two forms of options can be passed: short options and long options.

Short options are single-letter options with optional data. The format specifier for the short options is a string of allowed tokens. Option letters can be followed with a single : to indicate that the option requires a parameter or with a double :: to indicate that the parameter is optional.

Long options are an array of full-word options (for example, --help).The option strings can be followed by a single = to indicate that the option takes a parameter or by a double == if the parameter is optional.

For example, for a script to accept the -h and --help flags with no options, and for the --file option with a mandatory parameter, you would use the following code:

require_once "Console/Getopt.php";

$shortoptions = "h";
$longoptons = array("file=", "help");

$con = new Console_Getopt;
$args = Console_Getopt::readPHPArgv();
$ret = $con->getopt($args, $shortoptions, $longoptions);

The return value of getopt() is an array containing a two-dimensional array. The first inner array contains the short option arguments, and the second contains the long option arguments. Console_Getopt::readPHPARGV() is a cross-configuration way of bringing in $argv (for instance, if you have register_argc_argv set to off in your php.ini file).

I find the normal output of getopt() to be a bit obtuse. I prefer to have my options presented as a single associative array of key/value pairs, with the option symbol as the key and the option value as the array value. The following block of code uses Console_Getopt to achieve this effect:

function getOptions($default_opt, $shortoptions, $longoptions)
{
  require_once "Console/Getopt.php";
  $con = new Console_Getopt;
  $args = Console_Getopt::readPHPArgv();
  $ret = $con->getopt($args, $shortoptions, $longoptions);
  $opts = array();
  foreach($ret[0] as $arr) {
    $rhs = ($arr[1] !== null)?$arr[1]:true;
    if(array_key_exists($arr[0], $opts)) {
      if(is_array($opts[$arr[0]])) {
        $opts[$arr[0]][] = $rhs;
      }
    else {
      $opts[$arr[0]] = array($opts[$arr[0]], $rhs);
    }
  }
  else {
   $opts[$arr[0]] = $rhs;
  }
 }
 if(is_array($default_opt)) {
   foreach ($default_opt as $k => $v) {
     if(!array_key_exists($k, $opts)) {
       $opts[$k] = $v;
     }
   }
 }
 return $opts;
}

If an argument flag is passed multiple times, the value for that flag will be an array of all the values set, and if a flag is passed without an argument, it is assigned the Boolean value true. Note that this function also accepts a default parameter list that will be used if no other options match.

Using this function, you can recast the help example as follows:

$shortoptions = "h";
$longoptions = array("file=", "help");

$ret = getOptions(null, $shortoptions, $longoptions);

If this is run with the parameters -h --file=error.log, $ret will have the following structure:

Array
(
    [h] => 1
    [--file] => error.log
)


Previous
Table of Contents
Next