PHP Command Line Interface (CLI) options parser -- CommandLine::parseArgs($argv)
Here's a utility class that supports Linux style arguments for command line execution of PHP. It is high-performance (no regular expressions) and provides a flexible, simple and convenient syntax.
<?php
/**
* CommandLine class
*
* Command Line Interface (CLI) utility class.
*
* @author Patrick Fisher <patrick@pwfisher.com>
* @since August 21, 2009
* @see http://github.com/pwfisher/CommandLine.php
*/
class CommandLine
{
public static $args;
/**
* PARSE ARGUMENTS
*
* This command line option parser supports any combination of three types
* of options (switches, flags and arguments) and returns a simple array.
*
* [pfisher ~]$ php test.php --foo --bar=baz
* ["foo"] => true
* ["bar"] => "baz"
*
* [pfisher ~]$ php test.php -abc
* ["a"] => true
* ["b"] => true
* ["c"] => true
*
* [pfisher ~]$ php test.php arg1 arg2 arg3
* [0] => "arg1"
* [1] => "arg2"
* [2] => "arg3"
*
* [pfisher ~]$ php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs \
* > 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s
* [0] => "plain-arg"
* ["foo"] => true
* ["bar"] => "baz"
* ["funny"] => "spam=eggs"
* ["also-funny"]=> "spam=eggs"
* [1] => "plain arg 2"
* ["a"] => true
* ["b"] => true
* ["c"] => true
* ["k"] => "value"
* [2] => "plain arg 3"
* ["s"] => "overwrite"
*
* @author Patrick Fisher <patrick@pwfisher.com>
* @since August 21, 2009
* @see http://github.com/pwfisher/CommandLine.php
* #81042 function arguments($argv) by technorati at gmail dot com, 12-Feb-2008
* #78651 function getArgs($args) by B Crawford, 22-Oct-2007
* @usage $args = CommandLine::parseArgs($_SERVER['argv']);
*/
public static function parseArgs($argv)
{
$argv = $argv ? $argv : $_SERVER['argv'];
array_shift($argv);
$out = array();
foreach ($argv as $arg)
{
// --foo --bar=baz
if (substr($arg, 0, 2) === '--')
{
$eqPos = strpos($arg, '=');
// --foo
if ($eqPos === false)
{
$key = substr($arg, 2);
$value = isset($out[$key]) ? $out[$key] : true;
$out[$key] = $value;
}
// --bar=baz
else
{
$key = substr($arg, 2, $eqPos - 2);
$value = substr($arg, $eqPos + 1);
$out[$key] = $value;
}
}
// -k=value -abc
else if (substr($arg, 0, 1) === '-')
{
// -k=value
if (substr($arg, 2, 1) === '=')
{
$key = substr($arg, 1, 1);
$value = substr($arg, 3);
$out[$key] = $value;
}
// -abc
else
{
$chars = str_split(substr($arg, 1));
foreach ($chars as $char)
{
$key = $char;
$value = isset($out[$key]) ? $out[$key] : true;
$out[$key] = $value;
}
}
}
// plain-arg
else
{
$value = $arg;
$out[] = $value;
}
}
self::$args = $out;
return $out;
}
/**
* GET BOOLEAN
*/
public static function getBoolean($key, $default = false)
{
if (!isset(self::$args[$key]))
{
return $default;
}
$value = self::$args[$key];
if (is_bool($value))
{
return $value;
}
if (is_int($value))
{
return (bool)$value;
}
if (is_string($value))
{
$value = strtolower($value);
$map = array(
'y' => true,
'n' => false,
'yes' => true,
'no' => false,
'true' => true,
'false' => false,
'1' => true,
'0' => false,
'on' => true,
'off' => false,
);
if (isset($map[$value]))
{
return $map[$value];
}
}
return $default;
}
}
And here is a compacted version:
<?php
/**
* parseArgs Command Line Interface (CLI) utility function.
* @author Patrick Fisher <patrick@pwfisher.com>
* @see http://github.com/pwfisher/CommandLine.php
*/
function parseArgs($argv) {
$argv = $argv ? $argv : $_SERVER['argv']; array_shift($argv); $o = array();
foreach ($argv as $a) {
if (substr($a, 0, 2) == '--') { $eq = strpos($a, '=');
if ($eq !== false) { $o[substr($a, 2, $eq - 2)] = substr($a, $eq + 1); }
else { $k = substr($a, 2); if (!isset($o[$k])) { $o[$k] = true; } } }
else if (substr($a, 0, 1) == '-') {
if (substr($a, 2, 1) == '=') { $o[substr($a, 1, 1)] = substr($a, 3); }
else { foreach (str_split(substr($a, 1)) as $k) { if (!isset($o[$k])) { $o[$k] = true; } } } }
else { $o[] = $a; } }
return $o;
}
The compact version is very convenient for pasting into single-file scripts. It is totally equivalent to the airier version above.
Enjoy!
- Patrick
Great work, thx :-)
(thumbs up) & thanks that you've posted it.
Just can you give me some clue under what license if any I can include your implementation in one little project on my own so far called PDM ?
Or at least can I list your name in the references?
Thanks for the code. Made a mod so I can pass by reference an array which I've initialized with default values. Also modified the boolean part (--foo). In the compact version, it will only set to true if the key does not exist. Thanks.
@obi: attribution would be great, thanks. feel free to use this, that's why I posted it.
@george: the compact version is equivalent to the full version, it just doesn't set the value to itself -- an unnecessary operation I included for readability. We don't want to overwrite a string value with a boolean.
Very nice, thanks! I'll use it.
@pwfisher, Thank you! This is an incredibly useful class. I've been disappointed that the php cli did not take named arguments and you've fixed that :)
I know this post has been around for a while, but I wanted to let you know that I've found this to be incredibly useful.
Thanks tons!