php - PHP 命令行:以命令、子命令和参数的形式解析参数的有效方法
问题描述
我有一个脚本,应该如下调用:
script.php command subcommand --parameters parameter1="a" parameter2="b" parameterN="n"
例子:
script.php account backup import --parameters accont="UserA" backup_id=1
哪里command = 'account'
,subcommand = 'backup import'
和parameters = 'account="UserA"' backup_id=1
- 每个命令可以有多个子命令。
- 每个子命令只接受特定的参数(一些是强制性的,一些是可选的)。
有没有一种有效的方法来解析所有案例而无需 4 级嵌套开关?
谢谢你。
--- 添加信息以完成问题 ---- 这就是它的外观:
// command stack
$commands = array('group', 'account', 'context');
// subcommand stack
$group_subcommands = array(
'get',
'list',
);
$account_subcommands = array(
'add',
'backup import',
'backup list',
'mfa add',
'mfa del',
'mfa list',
'del',
'get',
'list',
'register',
'set',
'antivirus get',
'antivirus set',
);
$context_subcomands = array(
'list',
);
每个子命令的示例唯一参数:
account add --parameters account="user1" name="John" last_name="Smith" --city="London"
强制= 帐户、姓名、姓氏
可选= 城市
account del --parameters accont="UserA"
强制= 帐户
解决方案
您可以像这样存储您的命令/子命令:
$commands = ['group', 'account', 'context'];
$subCommands = [
'group' => ['get', 'list'],
'account' => ['add', 'backup import', 'backup list', 'mfa add', 'mfa del', 'mfa list', 'del', 'get', 'list', 'register', 'set', 'antivirus get', 'antivirus set'],
'context' => ['list']
];
并使用以下功能:
function parseCommand(string $commandLine): array
{
// Should ideally not be stored here, but somewhere like a config file, or at least in constants
$commands = ['group', 'account', 'context'];
$subCommands = [
'group' => ['get', 'list'],
'account' => ['add', 'backup import', 'backup list', 'mfa add', 'mfa del', 'mfa list', 'del', 'get', 'list', 'register', 'set', 'antivirus get', 'antivirus set'],
'context' => ['list']
];
if (!preg_match('/^(?<command>\w+)\s+(?<subCommand>[\w\s]+)(?:\s+--parameters\s+(?<paramsString>.*))?$/', $commandLine, $commandMatches)) {
throw new \InvalidArgumentException('Invalid syntax.');
}
if (!in_array($commandMatches['command'], $commands, true)
|| !in_array($commandMatches['subCommand'], $subCommands[$commandMatches['command']], true)) {
throw new \InvalidArgumentException('Invalid command and/or subcommand.');
}
$subCommandParams = [];
if (!empty($commandMatches['paramsString'] && preg_match_all('/(?<name>\w+)=(?:"(?<value1>[^"]*)"|(?<value2>\w*))"?/', $commandMatches['paramsString'], $paramsMatches, PREG_SET_ORDER))) {
foreach ($paramsMatches as $paramMatch) {
$subCommandParams[$paramMatch['name']] = $paramMatch['value1'] ?: $paramMatch['value2'];
}
}
return [$commandMatches['command'], $commandMatches['subCommand'], $subCommandParams];
}
我没有为可选/强制参数添加任何内容,但这应该很容易实现。
此外,理想情况下,您应该使用类来保存命令/子命令,并且可能还从函数返回专用对象(而不是数组)。
推荐阅读
- python - 预处理图像以读取文本 - 错误
- android - 需要有关选择 DB for Android 的帮助
- flutter - 动态更改 docId 时流不更新
- java - 尝试将文件读入byte[],但最终得到一个空长度数组
- flutter - Flutter:同时使用 Align bottom 和 SingleChildScrollView?
- python - IndexError:在图形/地图着色的约束满足问题 (CSP) 中列出超出范围的索引
- flutter - 将字符串数据解析为 int(断言失败:第 32 行 pos 14:'prevReading is int':不正确。)
- nestjs - Nestjs:无法读取“env”文件变量
- sql - 具有多个条件和表的 Linq To Sql Join
- python - 如何使用 PS4 控制器控制鼠标?