horde/argv

命令行参数解析库

v3.0.0alpha4 2022-11-04 00:00 UTC

README

内容

Horde_Argv 是一个带有各种操作的命令行参数解析库,提供帮助信息、分组选项等功能。它源自 Python 的 Optik (http://optik.sourceforge.net/)。

1   基本用法

尽管 Horde_Argv 非常灵活且功能强大,但你无需跳跃重重障碍或阅读大量文档就能开始使用。本文档旨在展示一些简单的用法模式,以帮助您开始在脚本中使用 Horde_Argv

要使用 Horde_Argv 解析命令行,你必须创建一个 Horde_Argv_Parser 实例并定义一些选项。你必须在任何使用 Horde_Argv 的脚本中导入 Horde_Argv_Parser 类,但建议使用自动加载器。

require_once 'Horde/Autoloader/Default.php';

在主程序早期创建解析器

$parser = new Horde_Argv_Parser();

然后你可以开始定义选项。基本语法是

$parser->addOption('opt_str', ..., array('attr' => 'value', ...));

即,每个选项都有一个或多个选项字符串,如 "-f" 或 "--file",以及一些选项属性,告诉 Horde_Argv 预期什么以及当它在命令行上遇到该选项时应该做什么。

通常,每个选项将有一个短选项字符串和一个长选项字符串,例如

$parser->addOption('-f', '--file', ...);

你可以定义任意数量的短选项字符串和长选项字符串,只要总共有至少一个选项字符串即可。

一旦定义了所有选项,告诉 Horde_Argv 解析程序的命令行

list($values, $args) = $parser->parseArgs();

(如果你愿意,可以向 parseArgs() 传递一个参数列表,但这很少有必要:默认情况下它使用 $_SERVER['argv']。)

parseArgs() 返回两个值

  • $values 是一个 Horde_Argv_Values 对象,包含所有选项的值 -- 例如,如果 "--file" 接受单个字符串参数,则 $values->file(或 $values['file'])将是用户提供的文件名,或者如果用户没有提供该选项则为 NULL。
  • $args 是解析选项后剩余的参数列表。

本教程文档仅涵盖四个最重要的选项属性:“action”(操作)、“type”(类型)、“dest”(目的地)和“help”(帮助)。其中,“action”是最基本的。

1.1   选项操作

操作告诉 Horde_Argv 在遇到命令行上的选项时应该做什么。在 Horde_Argv 中硬编码了一系列操作;添加新操作是高级主题,在 Extending Horde_Argv 中介绍。大多数操作告诉 Horde_Argv 将值存储在某个变量中 -- 例如,从命令行中获取一个字符串并将其存储在选项的属性中。

如果你没有指定选项操作,Horde_Argv 默认为 "store"。

1.1.1   存储操作

最常用的选项操作是 "store",它告诉 Horde_Argv 取下一个参数(或当前参数的剩余部分),确保它具有正确的类型,并将其存储在您选择的目的地。

例如

$parser->addOption(
    '-f', '--file',
    array('action' => 'store', 'type' => 'string', 'dest' => 'filename')
);

现在让我们构建一个假的命令行,并请求 Horde_Argv 对其进行解析

$args = array('-f', 'foo.txt');
list($values, $args) = $parser->parseArgs(args);

Horde_Argv 看到参数 "-f" 时,它会消费下一个参数 "foo.txt",并将其存储在 $values->filename 中,其中 values 是 parseArgs() 的第一个返回值。所以,在调用 parseArgs() 之后,$values->filename 的值是 "foo.txt"。

Horde_Argv 支持的一些其他选项类型是 "int" 和 "float"。这里有一个期望整数参数的选项

$parser->addOption('-n', array('type' => 'int', 'dest' => 'num'));

注意,我没有提供长选项,这是完全可以接受的。我也没有指定动作,因为默认值是 "store"。

让我们解析另一个假的命令行。这次,我们将选项参数直接放置在选项旁边 -- "-n42"(一个参数)与 "-n 42"(两个参数)等价。

list($values, $args) = $parser->parseArgs(array('-n42'));
echo $values->num;

将打印 "42"。

尝试 "float" 类型留给读者作为练习。

如果您不指定类型,Horde_Argv 假设 "string"。结合默认动作是 "store",这意味着我们的第一个例子可以更短。

$parser->addOption('-f', '--file', array('dest' => 'filename'))

如果您不提供目标位置,Horde_Argv 会从选项字符串中推断一个合理的默认值:如果第一个长选项字符串是 "--foo-bar",则默认目标位置是 "foo_bar"。如果没有长选项字符串,Horde_Argv 会查看第一个短选项:"-f" 的默认目标位置是 "f"。

在 "扩展 Horde_Argv" 中讨论了添加类型。

1.1.2   处理标志(布尔)选项

标志选项 -- 在看到特定选项时将变量设置为 TRUE 或 FALSE -- 非常常见。 Horde_Argv 通过两个单独的动作 "store_true" 和 "store_false" 支持它们。例如,您可能有一个详细标志,用 "-v" 打开,用 "-q" 关闭。

$parser->addOption('-v', array('action' => 'store_true', 'dest' => 'verbose'));
$parser->addOption('-q', array('action' => 'store_false', 'dest' => 'verbose'));

这里有两个具有相同目标的不同选项,这是完全可以接受的。(这意味着您在设置默认值时必须小心一点 -- 请参见下面的默认值。)

Horde_Argv 在命令行中看到 "-v" 时,它将特殊 "选项值" 对象的详细属性设置为 TRUE;当它看到 "-q" 时,它将详细属性设置为 FALSE。

1.1.3   其他操作

Horde_Argv 支持的一些其他动作是

这些在 高级用法选项回调 文档中讨论。

1.2   默认值

所有上述示例都涉及到在看到某些命令行选项时设置某个变量("目标")。如果从未看到这些选项会发生什么?由于我们没有提供任何默认值,它们都被设置为 NULL。通常这很好,但有时您想要更多的控制。为了满足这一需求,Horde_Argv 允许您为每个目标提供默认值,这些值在解析命令行之前分配。

首先,考虑详细/安静示例。如果我们希望 Horde_Argv 在看到 "-q" 之前将详细设置为 TRUE,那么我们可以这样做

$parser->addOption('-v', array('action' => 'store_true', 'dest' => 'verbose', $default => true));
$parser->addOption('-q', array('action' => 'store_false', 'dest' => 'verbose'));

令人惊讶的是,这正是等效的

$parser->addOption('-v', array('action' => 'store_true', 'dest' => 'verbose'));
$parser->addOption('-q', array('action' => 'store_false', 'dest' => 'verbose', $default => true));

这是因为您为选项的目标提供了默认值,并且这两个选项恰好具有相同的目标(详细变量)。

考虑这个

$parser->addOption('-v', array('action' => 'store_true', 'dest' => 'verbose', $default => false));
$parser->addOption('-q', array('action' => 'store_false', 'dest' => 'verbose', $default => true));

再次,详细的默认值将是 TRUE:为特定目标属性提供的最后一个默认值才是有效的。

指定默认值的一个更清晰的方法是 Horde_Argv_ParsersetDefaults() 方法,您可以在调用 parseArgs() 之前随时调用此方法。

$parser->setDefaults(array('verbose' => true));
$parser->addOption(...);
list($values, $args) = $parser->parseArgs();

与以前一样,给定选项目标指定的最后一个值才是有效的。为了清晰起见,尽量使用设置默认值的一种方法,而不是两种方法。

1.3   生成帮助信息

您将在每个脚本中使用的一个功能是:Horde_Argv 生成帮助信息的能力。您只需为每个选项提供一个帮助值。让我们创建一个新的解析器并填充用户友好的(文档化的)选项。

$usage = 'usage: %prog [options] arg1 arg2';
$parser = new Horde_Argv_Parser(array('usage' => $usage));
$parser->addOption(
    '-v', '--verbose',
    array('action' => 'store_true', 'dest' => 'verbose', $default => 1,
          'help' => 'make lots of noise [default]')
);
$parser->addOption(
    '-q', '--quiet',
    array('action' => 'store_false', 'dest' => 'verbose',
          'help' => 'be vewwy quiet (I'm hunting wabbits)')
);
$parser->addOption(
    '-f', '--filename',
    array('metavar' => 'FILE', 'help' => 'write output to FILE')
);
$parser->addOption(
    '-m', '--mode',
    array('default' => 'intermediate',
          'help' => 'interaction mode: one of "novice", "intermediate" [default], "expert"')
);

如果Horde_Argv在命令行中遇到'-h'或'--help',或者你只是调用$parser->printHelp(),它将以下内容打印到标准输出

usage: <yourscript> [options] arg1 arg2

options:
  -h, --help           show this help message and exit
  -v, --verbose        make lots of noise [default]
  -q, --quiet          be vewwy quiet (I'm hunting wabbits)
  -fFILE, --filename=FILE
                       write output to FILE
  -mMODE, --mode=MODE  interaction mode: one of 'novice', 'intermediate'
                       [default], 'expert'

这里有很多功能可以帮助Horde_Argv生成最佳的帮助信息

  • 脚本定义了自己的用法信息

    $usage = 'usage: %prog [options] arg1 arg2'; Horde_Argv将用法字符串中的"%prog"展开为当前脚本的名称,即basename($_SERVER['argv'][0])。展开后的字符串将在详细选项帮助之前打印。如果你不提供用法字符串,Horde_Argv将使用一个平淡但合理的默认值:"usage: %prog [options]",如果你的脚本不接收任何位置参数,这个默认值是合适的。

  • 每个选项都定义了一个帮助字符串,并且不需要担心换行——Horde_Argv会负责换行并使帮助输出看起来更美观。

  • 需要值的选项在其自动生成的帮助信息中表明这一点,例如对于"mode"选项

    -mMODE, --mode=MODE在这里,"MODE"被称为元变量:它表示用户期望提供给-m/--mode的参数。默认情况下,Horde_Argv将目标变量名转换为大写并用于元变量。有时,你可能不希望这样做——例如,--filename选项显式设置$metavar = "FILE",从而导致自动生成的选项描述:-fFILE, --filename=FILE 这对于节省空间来说很重要,但它还有其他作用:手动编写的帮助文本使用元变量"FILE",以提示用户"-fFILE"的正式语法和"写入输出到FILE"的非正式语义描述之间的联系。这是一种简单但有效的方法,可以使你的帮助文本更加清晰和有用。

1.4   打印版本号

类似于简短的用法字符串,Horde_Argv还可以打印出你程序的版本字符串。你必须提供这个字符串,作为Horde_Argv_Parser的版本参数

$parser = new Horde_Argv_Parser(array('usage' => '%prog [-f] [-q]', 'version' => '%prog 1.0'));

注意,"%prog"的展开方式与用法中的展开方式相同。除此之外,版本可以包含任何你喜欢的内容。当你提供它时,Horde_Argv会自动将"--version"选项添加到你的解析器中。如果它在命令行中遇到此选项,它将展开你的版本字符串(通过替换"%prog"),将其打印到标准输出,并退出。

例如,如果你的脚本名为"/usr/bin/foo",用户可能会这样做

$ /usr/bin/foo --version
foo 1.0

1.5   错误处理

对于基本用法,你需要知道的是当Horde_Argv在命令行中遇到错误时(例如,"-n4x",其中"-n"选项需要整数)的行为。 Horde_Argv将你的用法信息打印到标准错误,然后跟随一个有用且易于理解的错误信息。然后它通过调用exit()以非零退出状态终止。

如果你不喜欢这种方式,可以子类化Horde_Argv_Parser并重写parserError()方法。请参阅扩展Horde_Argv

1.6   综合运用

以下是基于Horde_Argv的脚本通常的样子

require_once 'Horde/Autoloader/Default.php';

[...]

$usage = 'usage: %prog [options] arg';
$parser = new Horde_Argv_Parser(array('usage' => $usage));
$parser->addOption(
    '-f', '--file',
    array('type' => 'string', 'dest' => 'filename',
          'help' => 'read data from FILENAME')
);
$parser->addOption(
    '-v', '--verbose',
    array('action' => 'store_true', 'dest' => 'verbose')
);
$parser->addOption(
    '-q', '--quiet',
    array('action' => 'store_false', 'dest' => 'verbose')
);
[... more options ...]

list($values, $args) = $parser->parseArgs();
if (count($args) != 1) {
    $parser->parserError('incorrect number of arguments');
}

if ($values->verbose) {
    printf('reading %s...%n', $values->filename);
}

[... go to work ...]