解析具有多个参数的命令行选项[getopt?]

时间:2013-03-17 22:04:10

标签: c parsing command-line-arguments

我需要我的程序从命令行中获取几个参数,语法如下:

getpwd -l user1 user2 ... -L -X -S...

因此,我需要让用户支持-l选项。我尝试使用getopt,但没有太多运气,只有当我将其他选项放在-l之前时才有效:

getpwd -L -X -S ... -l user1 user2 ...

我的代码(适用于-l-S):

    while((c = getopt(argc, argv, "l:S")) != -1){
    switch(c){
        case 'l':
            index = optind-1;
            while(index < argc){
                next = strdup(argv[index]); /* get login */
                index++;
                if(next[0] != '-'){         /* check if optarg is next switch */
                    login[lcount++] = next;
                }
                else break;
            }
            break;
        case 'S':
            sflag++;                        /* other option */
            break;
        case ':':                           /* error - missing operand */
            fprintf(stderr, "Option -%c requires an operand\n", optopt);
            break;
        case '?':                           /* error - unknown option */
            fprintf(stderr,"Unrecognized option: -%c\n", optopt);
            break;
      }
   }

optoptoptindextern int

所以,问题是:我可以使用getopt()函数(或getopt_long())吗?或者我是否必须编写自己的解析器来获得我需要的东西?

3 个答案:

答案 0 :(得分:12)

您的代码实际上非常非常接近工作。您唯一缺少的是getopt只希望您在-l之后使用一个参数,因此在第一个参数-l之后继续进行命令行解析。既然你要支持更多的参数,你必须告诉getopt从哪里开始再次解析命令行。

getopt将该信息存储在全局变量optind中。当我添加这一行时:

optind = index - 1;
break;案例的l之前

,您的代码开始有效。

答案 1 :(得分:0)

我写了一个用于解析命令行参数的C库(GPL许可证):

https://github.com/Vincenzo1968/myoptParser

https://github.com/Vincenzo1968/myoptParser/blob/master/how_to_use.md

您可以指定选项接受的最小和最大参数数。 您还可以指定选项采用零个或多个参数(或一个或多个,两个或更多,依此类推)。 当然,您可以指定固定数量的参数:零,一,二等。

您还可以指定参数的类型:string,integer或float。 解析器检查指定的数字和类型是否匹配,否则返回错误。

解析器还允许您指定是否需要选项。 您最终可以指定互斥选项。

答案 2 :(得分:0)

以下函数将为参数列表中的单个选项生成argc,argv对:

void GetArgsList (int argc, char *argv[], int* o_argc, char*** o_argv)
{
    char** ret = NULL;
    int i;
    int count = 0;

    for (i = optind - 1; i < argc ; ++i)
    {
        if (argv[i][0]=='-')
        {
            break;
        }
        else
        {
            if (NULL == ret)
            {
                ret = &argv[i];
            }
            count++;
        }
    }

    optind = i - 1;

    if (o_argc)
    {
        *o_argc = count;
    }

    *o_argv = ret;
}