我正在用php编写一个小的命令行应用程序。
处理命令行参数和选项的正确方法是什么?
似乎有argv数组,$ _ SERVER ['argv']和getopt,但何时使用它们却令人困惑?
此外,关于选项(例如“参数--option”)的最佳选择是什么?
您可以使用$ argv检索“原始”参数。另请参阅:http : //www.php.net/manual/de/reserved.variables.argv.php
例: php file.php a b c
$argv
将包含"file.php", "a", "b"
和"c"
。
使用getopts
获得的参数“解析”,PHP会为你做的肮脏的工作。因此,这可能是您希望通过传递参数的最佳方式--options
。请仔细查看http://www.php.net/manual/de/function.getopt.php。
它很好地描述了该功能。
有一天,我决定一劳永逸地打败这个怪物。我伪造了一个秘密武器——一个充当存储、解析器和参数查询函数的函数。
// You can initialize it with a multiline string:
arg("
-a --alpha bool Some explanation about this option
-b --beta bool Beta has some notes too
-n --number int Some number you need for the script
- --douglas int There is no short form of this
-o --others str A string of other things
");
// ... and now you have your arguments nicely wrapped up:
print arg("alpha"); // returns the value of -a or --alpha
print arg("a"); // same thing
print arg(); // returns the whole parsed array
print arg(1); // returns the first unnamed argument
print arg(2); // returns the second unnamed argument
print arg("douglas",42); // value of "douglas", or a reasonable default
Run Code Online (Sandbox Code Playgroud)
您需要做的就是将参数列表写为多行字符串。四列,看起来像一个帮助,但arg()
解析你的行并自动找出参数。
用两个或更多空格分隔列 - 就像你无论如何一样。
解析后,每个项目都将由一个字段数组表示,分别命名为char、word、type和help。如果参数没有短(字符)或长(字)版本,只需使用破折号。显然,两者都不是。
类型就是它们看起来的样子:bool表示参数后面没有值;如果缺少则为假,如果存在则为真。的INT和STR类型意味着必须有一个值,而INT确保它是一个整数。不支持可选参数。值可以用空格或等号分隔(即“-a=4”或“-a 4”)
在第一次调用之后,您将所有参数整齐地组织在一个结构中(转储它,您会看到),并且您可以按名称或编号查询它们的值。
函数 arg() 有第二个参数作为默认值,因此您永远不必担心缺少值。
arg()
函数本身function arg($x="",$default=null) {
static $arginfo = [];
/* helper */ $contains = function($h,$n) {return (false!==strpos($h,$n));};
/* helper */ $valuesOf = function($s) {return explode(",",$s);};
// called with a multiline string --> parse arguments
if($contains($x,"\n")) {
// parse multiline text input
$args = $GLOBALS["argv"] ?: [];
$rows = preg_split('/\s*\n\s*/',trim($x));
$data = $valuesOf("char,word,type,help");
foreach($rows as $row) {
list($char,$word,$type,$help) = preg_split('/\s\s+/',$row);
$char = trim($char,"-");
$word = trim($word,"-");
$key = $word ?: $char ?: ""; if($key==="") continue;
$arginfo[$key] = compact($data);
$arginfo[$key]["value"] = null;
}
$nr = 0;
while($args) {
$x = array_shift($args); if($x[0]<>"-") {$arginfo[$nr++]["value"]=$x;continue;}
$x = ltrim($x,"-");
$v = null; if($contains($x,"=")) list($x,$v) = explode("=",$x,2);
$k = "";foreach($arginfo as $k=>$arg) if(($arg["char"]==$x)||($arg["word"]==$x)) break;
$t = $arginfo[$k]["type"];
switch($t) {
case "bool" : $v = true; break;
case "str" : if(is_null($v)) $v = array_shift($args); break;
case "int" : if(is_null($v)) $v = array_shift($args); $v = intval($v); break;
}
$arginfo[$k]["value"] = $v;
}
return $arginfo;
}
// called with a question --> read argument value
if($x==="") return $arginfo;
if(isset($arginfo[$x]["value"])) return $arginfo[$x]["value"];
return $default;
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助很多迷失的灵魂,就像我一样。愿这个小函数揭示了不必编写帮助和解析器并使它们保持同步的美妙之处......此外,一旦解析,这种方法就闪电般快速,因为它缓存了变量,因此您可以调用它随心所欲。它的行为就像一个超级全球。
也可以在我的GitHub Gist上找到。