第九节 命令行选项(Command line options)

第九节 命令行选项(Command line options)

For CLI(command line interface) tools, command line options are popular. libapr provides APIs to handle command line options easily. Here is an excerpted code from getopt-sample.c.

在CLI(command line interface)工具中,命令行选项是比较流行的。APR提供了一些API来简化命令行选项的处理,这是getopt-sample.c示例文件中的一些代码。

/* excerpted from getopt-sample.c */
static const apr_getopt_option_t opt_option[] = {
    /* long-option, short-option, has-arg flag, description */
        { "in", 'i', TRUE, "input file" },      /* -i name or --in name */
        { "out", 'o', TRUE, "output file" },    /* -o name or --out name */
        { "help", 'h', FALSE, "show help" },    /* -h or --help */
        { NULL, 0, 0, NULL }, /* end (a.k.a. sentinel) */
};

At first, we should supply an array of apr_getopt_option_t elements. We call it option-list. Each element has four variables, i.e. long option, short option, flag of the trailing argument, and description. A long option is specified as '--help'. A short option is specified as '-h'. Short options are mandatory and long options are optional. We can set a long option to NULL. The third variable is flag of the existence of trailing argument. If a command line option works as '--in filename', i.e. the trailing argument is required, we have to set the flag to TRUE. If you run the program without the required argument, e.g. './a.out -in', it causes an error. The option-list must have a sentinel element as described above.

首先,我们应该提供一个apr_getopt_option_t类型的数组,我们叫他选项列表,每一个元素有4个变量组成,他们是完整的选项名称(long option),缩写的选项名称(short option),是否为带参数选项的标志位(trailing argument)和选项描述(description)。完整的选项名称类似于“--help”,缩写的选项名称如“-h”,缩写的选项名称是强制必须存在的,而完整的选项名称是可选的,你可以设置完整的选型名称为NULL.第三个变量是一个是否为带参数选项的标志位,如果命令行选项需要这样的格式“--in filename”,则这个标志位必须设置为TRUE,如果你运行这个程序没有填写这个参数,如“./a.out -in”,这将会导致发生错误。选项列表必须有一个哨兵元素(sentinel element)作为结束。

To parse actual command line options based on the option-list, we have to call apr_getopt_init() at first. That initializes apr_getopt_t object. Next, we keep calling apr_getopt_long() while it returns APR_SUCCESS. Here is an excerpted code from getopt-sample.c.

解析一个实际的命令行必须在一个选项列表的基础上,我们首先需要调用apr_getopt_init()来初始化apr_getopt_init()对象,接下来我们要保证在调用apr_getopt_long()时他的返回值是APR_SUCCESS,这里有一些示例代码出自getopt-sample.c文件。

/* excerpted from getopt-sample.c */

/* initialize apr_getopt_t */
apr_getopt_t *opt;
apr_getopt_init(&opt, mp, argc, argv);

/* parse the all options based on opt_option[] */
while ((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
    switch (optch) {
        case 'i':
        ...OMIT

During the loop, apr_getopt_long() processes the actual command line option one by one. If the option found is in the option-list, apr_getopt_long() returns APR_SUCCESS and set optch's value. When the option has the trailing argument, apr_getopt_long() parses it and set optarg's value.

在这个循环当中,apr_getopt_long()函数一个接一个的处理实际的命令行选项。如果一个选项在选项列表中被找到,apr_getopt_long()将返回APR_SUCCESS并且设置optch的值,当这个选项为一个带参数的选项时,apr_getopt_long()解析后出该参数时将该值设置到optarg中。

I show you an example. Let's think about the case that you run the program as './getopt-sample -h -i foo.txt'. At the first loop, apr_getopt_long() finds 'h' in the option-list. Then, apr_getopt_long() returns APR_SUCCESS and set optch to 'h'. At the next loop, apr_getopt_long() finds 'i' in the option-list and 'i' requiring the trailing argument, so it parses the trailing argument, 'foo.txt'. Thus, apr_getopt_long() returns APR_SUCCESS, and set optch to 'i' and optarg to "foo.txt". At the next loop, apr_getopt_long() finds no more options, so returns APR_EOF.

通过这个示例让我们考虑一下这个程序('./getopt-sample -h -i foo.txt')运行时发生的情况,在第一次循环的时,apr_getopt_long()在选项列表中找到了’h’选项,这个时候apr_getopt_long()返回APR_SUCCESS,并且将optch设置为’h’。在下一次循环中apr_getopt_long()发现了在选项列表中发现了’i’,’i’是一个带参数的选项,所以解析出参数’foo.txt’,这是apr_getopt_long()返回APR_SUCCESS,并且将optch设置成‘i’将optarg设置成"foo.txt",在下一次循环中apr_getopt_long()发现没有选项了,所以返回APR_EOF。