美文网首页
getopt 命令行参数解析

getopt 命令行参数解析

作者: devilisdevil | 来源:发表于2021-02-11 21:12 被阅读0次

    介绍

    • 用来解析命令行参数,argv是一个字符串数组,argc表示这个数组的长度,argv[0]是程序名,所以参数解析是从argv[1]开始。-开始的串表示选项(或者--开始,如果使用长选项),它后面的一个串表示选项的参数(也可能不是,因为选项可以没有参数)
    • 当没有参数解析的时候,函数返回-1
    • man 3 getopt
    • 功能说明
      • getopt: 获取短参数,它可以获取-a-l类型的短参数,也可以-al合并的获取到al
      • getopt_long: 在getopt的基础上获取长参数,它还可以获取--help这种参数
      • getopt_long_only: 也是在上一个函数基础上有所增加,输入长参数可以不用输入两个--,而是可以直接用-help

    SYNOPSIS

    • #include <unistd.h>

      • int getopt(int argc, char * const argv[],const char *optstring);
      • extern char *optarg; 存储选项的参数
      • extern int optind, opterr, optopt;
        • optind 是argv的下标,argv[optind]表示下一个待解析的参数,optind初始值为1
        • opterr 是否显示错误信息,非零显示,0不显示,一般我们把它设为0
        • optopt 如果出现错误,保存出错的那个选项
    • #include <getopt.h>

      • int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex)
      • int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex)

    参数说明

    • argcargv 就是传递给main函数的两个参数,argv就是程序运行时的程序名以及它的参数,是一个字符串数组,argc就是这个字符串数组的长度
    • optstring 指定需要解析的短参数,比如"abc:d:e::"表示有abcde这5种参数,而且ab不带参数,c带参数(后面跟的:表示后面必须跟一个参数),e可带可不带参数(后面跟的::表示选项参数是可选的,如果带参数必须紧挨着选项,也就是-exxx,不能有空格隔开如-e xxx,隔开则视为没有带参数),选项参数由optarg指向
    • longopts 指向option数组,包含了长选项的信息,数组最后一个元素(结构体)必须全部为0,下一节详细介绍这个结构体
    • longindex 如果不是null,那么将解析参数时将把它指向的变量设为对应的longopts数组的下标

    option结构体

    struct option {
        const char *name;    // --<name> name of the long option
        int         has_arg; // no_argument (or 0), required_argument (or 1), optional_argument (or 2)
        int        *flag;    // set *flag to val and returns 0 if not null
        int         val;     // value to return or to load into *flag
    }
    
    • name 表示长选项的名字,使用时就是用--<name>的形式
    • has_arg 用来指示这个选项的参数要求,no_argument或者0表示不带参数,required_argument或者1表示必须带参数,optional_argument或者2表示参数是可选的(可选的参数要带参数的话必须是--opt=param形式,不能用空格隔开,要用等于)
    • flag 通常设为0,若不为0,那么解析参数时将会把*flag设置为val,然后函数返回0
    • val 解析到参数时函数返回的值,或者设置*flag的值,通常把它设为对应的短参数字符

    错误参数处理

    两种错误,一个是出现不认识的选项,另一个是需要带参数的选项没有带参数

    • 默认情况,遇到错误,输出错误信息,把出错的那个选项保存到optopt,然后返回?
    • 如果opterr设为了0,则不输出错误信息,可以通过是否返回?来判定是否出错(默认情况opterr非0)
    • 如果optstring的第一个字符(也可能是第二个,如果开头有+-的话)是:,那么也不会输出错误信息,然后会返回:表示缺少选项参数或者返回?表示出现不认识的选项(这样就能把两种错误区分开了)

    使用getopt

    示例代码getopt-test.c

    // getopt-test.c
    // gcc -g -o getopt-test getopt-test.c
    #include <getopt.h>
    #include <stdio.h>
    
    int main(int argc, char *const argv[]) {
      char c;
      while ((c = getopt(argc, argv, "abc:d::")) != -1) {
        //   while ((c = getopt(argc, argv, ":abc:d::")) != -1) {
        switch (c) {
          case 'a':
          case 'b':
            printf("got %c\n", c);
            break;
          case 'c':
            puts("got 'c'");
            printf("argument for c is: %s\n", optarg);
            break;
          case 'd':
            puts("got d");
            if (optarg) {
              printf("argument for d is: %s\n", optarg);
            } else {
              puts("no argument for d");
            }
            break;
          default:
            printf("got %d (%c), optopt: %d (%c)\n", c, c, optopt, optopt);
            break;
        }
      }
      return 0;
    }
    

    运行情况

    • optstring前面不带:
    > ./getopt-test -d -d123 -c 456 -afc
    got d
    no argument for d
    got d
    argument for d is: 123
    got 'c'
    argument for c is: 456
    got a
    ./getopt-test: invalid option -- 'f'
    got 63 (?), optopt: 102 (f)
    ./getopt-test: option requires an argument -- 'c'
    got 63 (?), optopt: 99 (c)
    

    当遇到解析参数错误时(也就是上面说的两种错误),会输出错误提示,而且返回的字符都是?

    • optstring前面带:时,同样的命令
    > ./getopt-test -d -d123 -c 456 -afc
    got d
    no argument for d
    got d
    argument for d is: 123
    got 'c'
    argument for c is: 456
    got a
    got 63 (?), optopt: 102 (f)
    got 58 (:), optopt: 99 (c)
    

    这样可以区分出是哪一种错误(如果你需要的话),而且不会输出错误信息

    • 另外如果将opterr设为0的话也不会输出错误信息

    使用getopt_long

    示例代码getopt_long-test.c

    // getopt_long-test.c
    // gcc -g -o getopt_long-test getopt_long-test.c
    // ./getopt_long-test -e s --name sky --delete 123 -d123 --delete=123 --new --add -fe
    #include <getopt.h>
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char *const argv[]) {
      char c;
      //   opterr = 0;
      int ret, longind;
      struct option long_options[] = {{"add", no_argument, 0, 'a'},
                                      {"new", no_argument, 0, 'n'},
                                      {"name", required_argument, 0, 256},
                                      {"create", required_argument, 0, 'c'},
                                      {"delete", optional_argument, 0, 'd'},
                                      {0, 0, 0, 0}};
      while ((ret = getopt_long(argc, argv, "anc:e:d::", long_options, &longind)) != -1) {
    //   while ((ret = getopt_long(argc, argv, ":anc:e:d::", long_options, &longind)) != -1) {
        switch (ret) {
          case 'a':
            printf("got 'a', longind is: %d\n", longind);
            break;
          case 'n':
            printf("got 'n', longind is: %d\n", longind);
            break;
          case 256:
            printf("%s %s\n", long_options[longind].name, optarg);
            break;
          case 'c':
            printf("got 'c', longind is: %d\n", longind);
            break;
          case 'd':
            printf("got 'd', longind is: %d\n", longind);
            if (optarg) {
              printf("optional argument is: %s\n", optarg);
            } else {
              printf("no argument\n");
            }
            break;
          case 'e':
            printf("got 'e' -- %s\n", optarg);
            break;
          default:
            printf("got %d (%c), optopt: %d (%c)\n", c, c, optopt, optopt);
            break;
        }
      }
      return 0;
    }
    

    运行情况

    TODO, 有些问题,我试验时,遇到错误参数不会返回:或者?,总是返回0,这和文档不一致,还没搞清楚原因是什么

    more

    • shell中的getopt -- todo

    相关文章

      网友评论

          本文标题:getopt 命令行参数解析

          本文链接:https://www.haomeiwen.com/subject/ckzlxltx.html