PHP命令行:以命令、子命令和参数的形式解析参数的有效方法
我有一个脚本,应该按如下方式调用:PHP命令行:以命令、子命令和参数的形式解析参数的有效方法,php,Php,我有一个脚本,应该按如下方式调用: script.php command subcommand --parameters parameter1="a" parameter2="b" parameterN="n" 例如: script.php account backup import --parameters accont="UserA" backup_id=1 其中命令='account',子命令='backup import',和参数='account=“UserA”'backup\u
script.php command subcommand --parameters parameter1="a" parameter2="b" parameterN="n"
例如:
script.php account backup import --parameters accont="UserA" backup_id=1
其中命令='account'
,子命令='backup import'
,和参数='account=“UserA”'backup\u id=1
- 每个命令可以有多个子命令
- 每个子命令只接受特定的参数(一些是必需的,一些是可选的)
// 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"
必需的=account
您可以像这样存储命令/子命令:
$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];
}
函数parseCommand(字符串$commandLine):数组
{
//理想情况下,不应该存储在这里,而是存储在类似配置文件的地方,或者至少存储在常量中
$commands=['group','account','context'];
$subCommands=[
“组”=>[“获取”,“列表”],
“帐户”=>[“添加”、“备份导入”、“备份列表”、“mfa添加”、“mfa删除”、“mfa列表”、“删除”、“获取”、“列表”、“注册”、“设置”、“防病毒获取”、“防病毒设置”],
'上下文'=>['列表']
];
如果(!preg_match('/^(?\w+)\s+(?[\w\s]+)(?:\s+--parameters\s+(?*)?$/',$commandLine,$commandMatches)){
抛出new\InvalidArgumentException(“无效语法”);
}
如果(!in_数组($commandMatches['command'],$commands,true)
||!在数组中($commandMatches['subCommand'],$subCommands[$commandMatches['command']],true)){
抛出new\InvalidArgumentException('无效命令和/或子命令');
}
$subCommandParams=[];
如果(!empty($commandMatches['paramsString']和&preg_match_all('/(?\w+)=(?:“(?[^”]*)”)“(?\w*)”)“?/”,$commandMatches['paramsString'],$paramsMatches,preg_SET_ORDER))){
foreach($ParamsMatch作为$paramMatch进行匹配){
$subCommandParams[$paramMatch['name']]=$paramMatch['value1']?:$paramMatch['value2'];
}
}
返回[$commandMatches['command'],$commandMatches['subCommand'],$subCommandParams];
}
我没有为可选/强制性参数添加任何内容,但这应该很容易实现
此外,理想情况下,您应该使用类来保存命令/子命令,并可能从函数返回专用对象(而不是数组)
演示:非常感谢您的回答。我有几点我不知道如何让它工作:1。双引号参数未正确读取。例如:last_name=“Smith Parker”,只显示
[last_name]=>Smith
。2.我可以将任何未经验证的单词作为命令或子命令传递(如开关)。3.您能告诉我更多关于使用类和返回对象的信息吗?谢谢。@jmox查看我更新的答案/演示链接。我调整了regexp以允许双引号内有空格(实际上还有任何空格)。还添加了基于已定义数组(我忘记了)的无效命令/子命令检查。这样更好吗?