Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP命令行:以命令、子命令和参数的形式解析参数的有效方法_Php - Fatal编程技术网

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

  • 每个命令可以有多个子命令
  • 每个子命令只接受特定的参数(一些是必需的,一些是可选的)
有没有一种有效的方法可以在不使用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"

必需的=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以允许双引号内有空格(实际上还有任何空格)。还添加了基于已定义数组(我忘记了)的无效命令/子命令检查。这样更好吗?