不知道别人有没有这样的需求,今天下午需要做一个自己的命令系统。
需要解析来自用户传递的命令行字符串。
例如这样的命令行,把里面的命令和参数都提取出来。
cmd -y 10 'test'
考虑一般比较常见的兼容,正则表达式可以直接使用。
// 带分组名
(?:(?<s>['"])?(?<v>.+?)?(?:(?<!\\)\k<s>)|(?<u>[^'"\s]+))
// 不带分组名
(?:(['"])?(.+?)?(?:(?<!\\)\1)|([^'"\s]+))
一个自己写的比较极端的命令行解析情况
cmd -n "rel'o\"a d" 'te"s\' t' upload ""
测试结果
使用这个表达式匹配多个结果即可.
使用时注意,因考虑有些语言不允许两个分组名相同,或者不允许使用分组名。
值可能会存在两种情况,可以根据 's'/1 组的值是否为空来选择获取哪个 'v'/2 or 'u'/3 的值。
PHP使用示例
/**
* 解析命令行
* @param string $str 命令行字符串
* @return array/bool 解析结果数组 失败返回false
*/
function exp_command($str)
{
// 正则表达式
$regEx = '#(?:(?<s>[\'"])?(?<v>.+?)?(?:(?<!\\\\)\k<s>)|(?<u>[^\'"\s]+))#';
// 匹配所有
if(!preg_match_all($regEx, $str, $exp_list)) return false;
// 遍历所有结果
$cmd = array();
foreach ($exp_list['s'] as $id => $s) {
// 判断匹配到的值
$cmd[] = empty($s) ? $exp_list['u'][$id] : $exp_list['v'][$id];
}
return $cmd;
}
// 命令行字符串
$str = 'cmd -n "rel\'o\"a d" \'te"s\' t\' upload ""';
$cmd = exp_command($str);
print_r($cmd);
/* 打印输出结果
Array
(
[0] => cmd
[1] => -n
[2] => rel'o\"a d
[3] => te"s
[4] => t
[5] => upload
[6] =>
)
*/