如何合并包含常规CLI选项的两个字符串(即任何getopt()
都可以正确解析的字符串)?
第一个是从配置文件中提取的,第二个是从Symfony的ConsoleInputgetArgument()
中提取的。我也可以从$GLOBALS['argv']
获得第二个。我想把它们结合起来,这样我就可以和它们一起启动另一个程序。
任何一个字符串都可以包含短选项和长选项,既可以包含值也可以不包含值。
示例
例如,config.yml
包含
phpunit_arguments: -d xdebug.mode=off --columns=115
然后用户可以用CCD_ 5调用我的程序。我想合并这些字符串,这样我就可以得到:
-d xdebug.mode=off --columns=95 --debug
来自第一个字符串的columns
被来自第二个字符串的一个重写。
尝试1失败:转换为数组
如果我可以将这些字符串放入如下数组中,那么我就可以使用array_merge_recursive()
:
array(
'-d xdebug.mode' => 'off',
'--columns' => 115
)
array(
'--columns' => 95,
'--debug'
)
但要做到这一点,我需要一个了解CLI选项的解析器。
我看了以下内容,但似乎没有一个是为了获取任意字符串并返回解析后的数组而设计的。
- PHP的
getopt()
- Symfony的
ConsoleInput
- PHPUnit的
TextUICliArgumentsBuilder
- docopt.php
- Commando
- GetOptionKit
失败的尝试2:连接
我试着只是将两个字符串连接起来,而不是将它们合并,这在技术上是可行的,但它会产生用户体验问题。我的程序向用户显示args,而concat'd字符串将包含重复项,这对一些人来说会很困惑。程序在运行时也接受输入,并重新生成选项;随着时间的推移,添加到先前的字符串会像滚雪球一样越滚越大,混淆/UX的情况也会更糟。
例如,在设置groups
几次后,它将以结束
-d xdebug.mode=off --columns=95 --debug --groups=database --groups=file --groups=console
您可以创建自己的函数,该函数将智能合并配置参数和CLI参数。使用单个正则表达式,我们可以提取像-
或--
这样的前置符号、命令名和值的相等字符。
使用正则表达式和循环合并参数
请阅读内联评论
<?php
echo "PHP ".phpversion().PHP_EOL;
// $config = yaml_parse_file('config.yml');
// Load a JSON file instead of YAML, because repl.it
// does not have php_yaml extension enabled
$json = file_get_contents("config.json");
$config = json_decode($json, TRUE);
$phpunit_arguments = explode(' ', $config['phpunit_arguments']);
echo "phpunit_arguments:n";
print_r($phpunit_arguments);
// Merge the params
$params = mergeConfigParameters($phpunit_arguments);
// Concatenate and print all params
echo "cli args:n";
echo implode(' ', $params).PHP_EOL;
function mergeConfigParameters($config_params) {
$argv = $GLOBALS['argv'];
array_shift($argv); // Remove script file from CLI arguments
if (empty($argv)) {
// If we run the file without CLI arguments,
// apply some fake argv arguments for demontration
$argv = [
'-d',
'xdebug.mode=on',
'--columns=95',
'--debug',
'--groups=database',
'--groups=file',
'--groups=console'
];
}
echo "argv:n";
print_r($argv);
// Merge all parameters, CLI arguments and from config
$all_params = array_merge($config_params, $argv);
echo "all_params:n";
print_r($all_params);
// We'll save all the params here using assoc array
// to identify and handle/override duplicate commands
$params = [];
foreach ($all_params as $param) {
// This regex will match everything:
// -d
// xdebug.mode=off
// --columns=95
// and create 4 groups:
// 1: the pre char(s), - or --
// 2: the cmd, actual command
// 3: the eq char, =
// 4: the value
if (preg_match('/^(-[-]?)?([w.]+)(=?)(.*)/', $param, $matches)) {
// Destructure matches
[, $pre, $cmd, $eq, $value] = $matches;
$param = [
'pre' => $pre,
'cmd' => $cmd,
'eq' => $eq,
'value' => $value
];
// If the command is set, merge it with the previous,
// else add it to $params array
if (isset($params[$cmd])) {
$params[$cmd] = array_merge($params[$cmd], $param);
} else {
$params[$cmd] = $param;
}
}
}
$merged = [];
// Loop throu all unique params and re-build the commands
foreach ($params as $param) {
[
'pre' => $pre,
'cmd' => $cmd,
'eq' => $eq,
'value' => $value
] = $param;
if (!empty($pre)) {
$cmd = $pre.$cmd;
}
if (!empty($eq)) {
$cmd .= $eq;
if (!empty($value)) {
$cmd .= $value;
}
}
$merged[] = $cmd;
}
echo "merged:n";
print_r($merged);
// Finally we have all unique commands compiled again
return $merged;
}
结果
运行此命令:
php main.php -d xdebug.mode=on --columns=95 --debug --groups=database --groups=file --groups=console
使用此config.yml
:
phpunit_arguments: -d xdebug.mode=off --columns=115 --number=1234
将输出以下内容:
PHP 7.2.24-0ubuntu0.18.04.7
phpunit_arguments:
Array
(
[0] => -d
[1] => xdebug.mode=off
[2] => --columns=115
[3] => --number=1234
)
argv:
Array
(
[0] => -d
[1] => xdebug.mode=on
[2] => --columns=95
[3] => --debug
[4] => --groups=database
[5] => --groups=file
[6] => --groups=console
)
all_params:
Array
(
[0] => -d
[1] => xdebug.mode=off
[2] => --columns=115
[3] => --number=1234
[4] => -d
[5] => xdebug.mode=on
[6] => --columns=95
[7] => --debug
[8] => --groups=database
[9] => --groups=file
[10] => --groups=console
)
merged:
Array
(
[0] => -d
[1] => xdebug.mode=on
[2] => --columns=95
[3] => --number=1234
[4] => --debug
[5] => --groups=console
)
cli args:
-d xdebug.mode=on --columns=95 --number=1234 --debug --groups=console
因此,我们可以看到参数-d xdebug.mode=off
和--columns=115
已经合并并覆盖为CLI参数-d xdebug.mode=on --columns=95
,而且我们只有最后一个--groups=console
集合。
运行它
你可以在这个repl.it.上在线检查这个解析工作