我正在用 php 编写一个小型命令行应用程序。
处理命令行参数和选项的正确方法是什么?
似乎有 argv 数组、$_SERVER['argv'] 和 getopt,但是什么时候使用它们令人困惑?
另外关于选项,即“argument --option”,获得这些的最佳方法是什么?
我正在用 php 编写一个小型命令行应用程序。
处理命令行参数和选项的正确方法是什么?
似乎有 argv 数组、$_SERVER['argv'] 和 getopt,但是什么时候使用它们令人困惑?
另外关于选项,即“argument --option”,获得这些的最佳方法是什么?
有一天,我决定一劳永逸地打败这个怪物。我伪造了一个秘密武器——一个充当存储的函数、一个解析器和一个参数查询函数。
// 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
您需要做的就是将参数列表写为多行字符串。四列,看起来像一个帮助,但arg()
会解析你的行并自动找出参数。
用两个或多个空格分隔列 - 就像你一样。
解析后,每个项目将由一个字段数组表示,分别命名为char、word、type和help。如果参数没有短 (char) 或长 (word) 版本,只需使用破折号。显然,两者都不是。
类型就是它们看起来的样子: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;
}
我希望这可以帮助很多迷失的灵魂,就像我一样。愿这个小函数阐明不必编写帮助和解析器并使它们保持同步的美妙之处......此外,一旦解析,这种方法非常快,因为它缓存了变量,所以你可以调用它尽可能多随心所欲。它就像一个超全球。
也可以在我的GitHub Gist上找到。
您可以使用 $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
很好的描述了这个函数。