详细讲解PHP中从命令行CLI参数列表中获取选项方法-getopt

在PHP中,getopt函数用于从命令行参数列表中解析选项,反正是绝口不提$argv。这对于编写命令行工具或脚本非常有用,因为它允许你轻松地处理用户提供的选项和参数。

特性$argvgetopt
用途获取所有命令行参数解析命令行选项(短选项和长选项)
处理的内容所有传递的参数只处理选项(如 -a, --option
解析复杂性需要手动解析自动解析短选项和长选项
适用场景简单的参数传递复杂命令行选项(特别是带有选项和值的参数)
返回格式数组,按顺序存储关联数组,按选项名称存储

函数签名

getopt(string $short_options, array $long_options = [], int &$rest_index = null): array|false

参数详解

  1. $short_options (string)

    • 这是一个字符串,定义了短选项(即单个字符的选项)。
    • 每个字符代表一个选项。例如,"ab"表示选项-a-b
    • 如果选项需要一个参数,可以在字符后面加上冒号:。例如,"a:b"表示-a需要一个参数,而-b不需要参数。
    • 如果选项需要一个可选参数,可以在字符后面加上两个冒号::。例如,"a::b"表示-a可以有一个可选参数,而-b不需要参数。
  2. $long_options (array, 可选)

    • 这是一个数组,定义了长选项(即多个字符的选项)。
    • 每个数组元素是一个字符串,表示一个长选项。例如,["help", "verbose"]表示选项--help--verbose
    • 如果选项需要一个参数,可以在选项名称后面加上冒号:。例如,["file:", "verbose"]表示--file需要一个参数,而--verbose不需要参数。
    • 如果选项需要一个可选参数,可以在选项名称后面加上两个冒号::。例如,["file::", "verbose"]表示--file可以有一个可选参数,而--verbose不需要参数。
  3. $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);
?>

解释

  1. 定义选项$options = "a:b:"; 表示我们有两个选项 -a-b,它们都需要一个值。
  2. 初始化 rest_index$rest_index = 0; 初始化 rest_index 变量。
  3. 解析命令行参数$params = getopt($options, [], $rest_index); 解析命令行参数,并将解析停止时的索引赋值给 $rest_index
  4. 输出解析结果print_r($params); 输出解析后的选项和值。
  5. 输出 rest_indexecho "Rest index: " . $rest_index . "\n"; 输出解析停止时的索引。
  6. 输出剩余的参数$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可以一览全余,但也会有些特殊场景需要,所以且用且珍惜吧


技术要点

  1. 选项参数的解析getopt函数能够处理短选项和长选项,并且可以指定选项是否需要参数或可选参数。
  2. 错误处理:如果用户提供了无效的选项或缺少必需的参数,getopt会返回false,你可以根据返回值进行错误处理。
  3. 剩余参数的处理:通过$rest_index参数,你可以获取未解析的参数,这对于处理选项之后的其他命令行参数非常有用。

涉及的难点

  1. 选项的定义:正确地定义短选项和长选项,并指定它们是否需要参数或可选参数,这需要对getopt函数的参数格式有深入的理解。
  2. 参数的解析:处理用户可能提供的各种选项组合,确保脚本能够正确解析并处理这些选项。
  3. 错误处理:当用户提供了无效的选项或缺少必需的参数时,如何优雅地处理这些错误,并提供有用的错误信息。

通过合理使用getopt函数,你可以轻松地编写功能强大且用户友好的命令行工具。

标签: PHP

相关文章

PHP中利用 popen 和 pclose 实现多进程的简单方案

在 PHP 中,popen 和 pclose 函数用于打开一个指向进程的管道,并允许你通过该管道与进程进行通信。popen 函数会启动一个新的进程,并返回一个文件指针,你可以通过该指针读取或写入...

Typecho插件开发手册

插件的基本结构在 Typecho 中,插件通常是一个独立的 PHP 文件,默认放置在usr/plugins/目录下。插件文件名即为插件名,插件类名也应与文件名相同。插件必须实现 Typecho_...

Typecho博客系统的xmlrpc的使用附PHP示例代码

XML-RPC 是一种远程过程调用(RPC)协议,它使用 XML 编码请求和响应,并通过 HTTP 进行传输。XML-RPC 允许客户端调用远程服务器上的方法,并获取返回结果。这种协议简单、轻量...

php+mysql中如何处理嵌套(子)事务并保持原子性一致

在PHP和MySQL中处理子事务并保持原子性一致性是一个复杂但非常重要的问题,尤其是在处理涉及多个数据库操作的业务逻辑时。以下是一些关键的解决方案、思路、技术要点和涉及的难点讲解。解决方案与思路...

如何使用Go编写跨平台组件并让Java或PHP调用

在现代软件开发中,跨语言调用是一个常见的需求。假设我们有一个用Go语言编写的组件,我们希望Java或PHP能够直接调用这个组件中对外提供的方法。为了实现这一目标,我们可以使用以下几种方法:1. ...

深入解析PHP的filter_var函数及其应用场景

在PHP开发中,数据的过滤与验证是至关重要的环节。PHP的 filter_var 函数提供了一种简洁而强大的方式来对输入数据进行验证和过滤。本篇文章将从专业的角度详细介绍 filter_var ...

图片Base64编码

CSR生成

图片无损放大

图片占位符

Excel拆分文件