详细讲解PHP中从命令行CLI参数列表中获取选项方法-getopt
在PHP中,getopt
函数用于从命令行参数列表中解析选项,反正是绝口不提$argv。这对于编写命令行工具或脚本非常有用,因为它允许你轻松地处理用户提供的选项和参数。
特性 | $argv | getopt |
---|---|---|
用途 | 获取所有命令行参数 | 解析命令行选项(短选项和长选项) |
处理的内容 | 所有传递的参数 | 只处理选项(如 -a , --option ) |
解析复杂性 | 需要手动解析 | 自动解析短选项和长选项 |
适用场景 | 简单的参数传递 | 复杂命令行选项(特别是带有选项和值的参数) |
返回格式 | 数组,按顺序存储 | 关联数组,按选项名称存储 |
函数签名
getopt(string $short_options, array $long_options = [], int &$rest_index = null): array|false
参数详解
$short_options
(string)- 这是一个字符串,定义了短选项(即单个字符的选项)。
- 每个字符代表一个选项。例如,
"ab"
表示选项-a
和-b
。 - 如果选项需要一个参数,可以在字符后面加上冒号
:
。例如,"a:b"
表示-a
需要一个参数,而-b
不需要参数。 - 如果选项需要一个可选参数,可以在字符后面加上两个冒号
::
。例如,"a::b"
表示-a
可以有一个可选参数,而-b
不需要参数。
$long_options
(array, 可选)- 这是一个数组,定义了长选项(即多个字符的选项)。
- 每个数组元素是一个字符串,表示一个长选项。例如,
["help", "verbose"]
表示选项--help
和--verbose
。 - 如果选项需要一个参数,可以在选项名称后面加上冒号
:
。例如,["file:", "verbose"]
表示--file
需要一个参数,而--verbose
不需要参数。 - 如果选项需要一个可选参数,可以在选项名称后面加上两个冒号
::
。例如,["file::", "verbose"]
表示--file
可以有一个可选参数,而--verbose
不需要参数。
$rest_index
(int, 可选) (PHP版本>=7.1.0才有此参数)- 这是一个引用变量,用于存储未解析的参数的索引。
- 如果提供了这个参数,
getopt
函数会将其设置为第一个未解析的参数的索引。 - 这对于处理选项之后的剩余参数非常有用。
返回值
- 如果成功,
getopt
返回一个关联数组,键是选项名称,值是选项的参数(如果有的话)。 - 如果失败,
getopt
返回false
。
使用示例
假设我们有一个PHP脚本example.php
,我们希望从命令行中获取以下选项:
-f
或--file
:指定一个文件路径。-v
或--verbose
:启用详细输出。-h
或--help
:显示帮助信息。
<?php
// 定义短选项和长选项
$short_options = "f:vh";
$long_options = ["file:", "verbose", "help"];
// 解析命令行参数
$options = getopt($short_options, $long_options);
// 处理解析结果
if (isset($options['h']) || isset($options['help'])) {
echo "Usage: php example.php [options]\n";
echo "Options:\n";
echo " -f, --file <file> Specify a file path\n";
echo " -v, --verbose Enable verbose output\n";
echo " -h, --help Display this help message\n";
exit(0);
}
if (isset($options['f'])) {
$file = $options['f'];
echo "File path: $file\n";
} elseif (isset($options['file'])) {
$file = $options['file'];
echo "File path: $file\n";
}
if (isset($options['v']) || isset($options['verbose'])) {
echo "Verbose mode enabled\n";
}
再来一个单字符选项示例
使用短选项 -c、-l 和 -d 来分别表示更新分类、采集文章列表和采集文章内容
使用 getopt("cdl") 来解析这些选项,c、d 和 l 是选项的缩写
// 命令行参数解析
$options = getopt("cdl");
if (isset($options['c'])) {
// 更新分类
updateCategories();
} elseif (isset($options['l'])) {
// 采集文章列表
scrapeArticleList();
} elseif (isset($options['d'])) {
// 采集文章内容
getContent();
} else {
// 显示帮助信息
echo "Usage:\n";
echo " -c 更新分类列表\n";
echo " -l 采集文章列表\n";
echo " -d 采集文章内容\n";
}
更新分类:php index.php -c
采集文章列表:php index.php -l
采集文章内容:php index.php -d
这儿要说明一下的是
如果你希望使用类似 -c、-d、-l 的单字符选项来执行操作,并且这些选项是独立的、无需参数的开关,那么应该使用如下的 getopt 调用 $options = getopt("cdl");
这样解析的选项 -c、-d、-l 都是无需附加参数的开关。
如果你需要这些选项(例如 -c、-d、-l)后面带有参数,那么你应该使用带有冒号的格式,就用 $options = getopt("c:d:l:");
这意味着:-c 后面必须有一个参数。 -d 也是 -l 同理
示例命令行调用
php example.php -f /path/to/file -v
输出:
File path: /path/to/file
Verbose mode enabled
特殊情况示例
$options = getopt("abc");
var_dump($options);
调用php example.php -a -baa -c
返回
array(3) {
["a"]=>
array(3) {
[0]=>
bool(false)
[1]=>
bool(false)
[2]=>
bool(false)
}
["b"]=>
bool(false)
["c"]=>
bool(false)
}
这儿a
的长度有三个,这是为什么呢?
这是因为 getopt 函数解释命令行参数时,遇到了重复的 -a。实际上,当你输入 -baa,PHP 认为:
-b 是一个带参数的选项(但是我们设置的又是-b不需要参数),所以b后面的两个a就会被解释为多个独立的 -a。
在内部,getopt 函数对 -baa 进行了如下解释:
- -b 被看作是一个选项。
- a 被看作是重复的三次标志,虽然输入 -a -b -a -a 并不是标准输入格式,但 getopt 并没有严格限制这种用法,结果是它将 a 视作三个开关标志,所以你得到了一个 a 数组,包含三个 false 值。
rest_index的解读
rest_index
参数是一个可选的引用参数,用于指示参数解析停止时的索引位置。
官方注释的意思是,如果你传递了一个变量(例如 $rest_index
)作为 getopt()
的最后一个参数,那么当 getopt()
解析参数时,如果遇到一个无法解析的参数(例如一个非选项参数),它会将当前的索引位置赋值给 $rest_index
,然后停止解析。
示例代码
假设我们有以下命令行参数:
php script.php -a 1 -b 2 file1 file2 file3
我们希望解析选项 -a
和 -b
,并且知道在解析完选项后,剩下的参数是什么。
<?php
// 定义选项
$options = "a:b:";
// 初始化 rest_index
$rest_index = 0;
// 解析命令行参数
$params = getopt($options, [], $rest_index);
// 输出解析结果
print_r($params);
// 输出 rest_index
echo "Rest index: " . $rest_index . "\n";
// 输出剩余的参数
$remaining_args = array_slice($argv, $rest_index);
print_r($remaining_args);
?>
解释
- 定义选项:
$options = "a:b:";
表示我们有两个选项-a
和-b
,它们都需要一个值。 - 初始化
rest_index
:$rest_index = 0;
初始化rest_index
变量。 - 解析命令行参数:
$params = getopt($options, [], $rest_index);
解析命令行参数,并将解析停止时的索引赋值给$rest_index
。 - 输出解析结果:
print_r($params);
输出解析后的选项和值。 - 输出
rest_index
:echo "Rest index: " . $rest_index . "\n";
输出解析停止时的索引。 - 输出剩余的参数:
$remaining_args = array_slice($argv, $rest_index);
使用array_slice()
函数获取剩余的参数,并输出它们。
输出结果
假设命令行参数为 php script.php -a 1 -b 2 file1 file2 file3
,输出结果可能如下:
Array
(
[a] => 1
[b] => 2
)
Rest index: 5
Array
(
[0] => file1
[1] => file2
[2] => file3
)
解释输出结果
Array ([a] => 1 [b] => 2)
:解析后的选项和值。Rest index: 5
:解析停止时的索引位置。Array ([0] => file1 [1] => file2 [2] => file3)
:剩余的参数。
当然虽然看着有点多余,而且索引的位置居然不是从0开始数的...,直接用$argv可以一览全余,但也会有些特殊场景需要,所以且用且珍惜吧
技术要点
- 选项参数的解析:
getopt
函数能够处理短选项和长选项,并且可以指定选项是否需要参数或可选参数。 - 错误处理:如果用户提供了无效的选项或缺少必需的参数,
getopt
会返回false
,你可以根据返回值进行错误处理。 - 剩余参数的处理:通过
$rest_index
参数,你可以获取未解析的参数,这对于处理选项之后的其他命令行参数非常有用。
涉及的难点
- 选项的定义:正确地定义短选项和长选项,并指定它们是否需要参数或可选参数,这需要对
getopt
函数的参数格式有深入的理解。 - 参数的解析:处理用户可能提供的各种选项组合,确保脚本能够正确解析并处理这些选项。
- 错误处理:当用户提供了无效的选项或缺少必需的参数时,如何优雅地处理这些错误,并提供有用的错误信息。
通过合理使用getopt
函数,你可以轻松地编写功能强大且用户友好的命令行工具。
版权声明:本文为原创文章,版权归 全栈开发技术博客 所有。
本文链接:https://www.lvtao.net/dev/php-getopt.html
转载时须注明出处及本声明