7

我正在用 php 编写一个小型命令行应用程序。

处理命令行参数和选项的正确方法是什么?

似乎有 argv 数组、$_SERVER['argv'] 和 getopt,但是什么时候使用它们令人困惑?

另外关于选项,即“argument --option”,获得这些的最佳方法是什么?

4

2 回答 2

6

论据,变得容易

有一天,我决定一劳永逸地打败这个怪物。我伪造了一个秘密武器——一个充当存储的函数、一个解析器和一个参数查询函数。


    //  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、typehelp。如果参数没有短 (char) 或长 (word) 版本,只需使用破折号。显然,两者都不是。

  • 类型就是它们看起来的样子:bool表示参数后面没有值;如果缺少则为假,如果存在则为真。intstr类型意味着必须有一个值,而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上找到。

于 2019-03-08T13:30:58.803 回答
5

您可以使用 $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 很好的描述了这个函数。

于 2012-08-20T19:29:08.367 回答