getopt处理命令行参数

linux程序设计-getopt处理命令行参数

  • 下面是POSIX标准中关于程序名、参数的约定:

    1. 程序名不宜少于2个字符且不多于9个字符;=
    2. 程序名应只包含小写字母和阿拉伯数字;
    3. 选项名应该是单字符活单数字,且以短横‘-‘为前綴;
    4. 多个不需要选项参数的选项,可以合并。(譬如:foo -a -b -c ---->foo -abc)
    5. 选项与其参数之间用空白符隔开;
    6. 选项参数不可选。
    7. 若选项参数有多值,要将其并为一个字串传进来。譬如:myprog -u “arnold,joe,jane”。这种情况下,需要自己解决这些参数的分离问题。
    8. 选项应该在操作数出现之前出现。
    9. 特殊参数‘–'指明所有参数都结束了,其后任何参数都认为是操作数。
    10. 选项如何排列没有什么关系,但对互相排斥的选项,如果一个选项的操作结果覆盖其他选项的操作结果时,最后一个选项起作用;如果选项重复,则顺序处理。
    11. 允许操作数的顺序影响程序行为,但需要作文档说明。
    12. 读写指定文件的程序应该将单个参数’-'作为有意义的标准输入或输出来对待。
  • 函数功能:对命令行的选项进行处理

  • 函数返回值:如果命令行中输入的选项可以和optstring字符串中的字符选项匹配,那么返回选项字符,如果不在有可以识别的选项返回-1

  • 函数原型:

int getopt(int argc, char *argv[], const char *optstring);
  • 参数:

    1. argc:主函数的参数

    2. argv:主函数的参数

    3. optstring:选项字母组成的字串,举例“ab:c::d”,做一下分析

      • a:表示命令行有一个-a选项
      • b::表示命令行有一个-b选项,并且带有一个选项参数,选项和选项参数之间用空格隔开
      • c:::表示命令行有一个-c选项,该选项带有一个选项参数,并且选项参数和选项之间没有空格
      • 如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
        1. “无效选项” —— getopt()返回’?’,并且optopt包含了无效选项字符(这是正常的行为)。
        2. “缺少选项参数” —— getopt()返回’:’
      • 如果optstring的第一个字符不是冒号,那么getopt()返回’?’,这会使得这种情况不能与无效选项的情况区分
  • getopt设置的全局变量:

    1. char *optarg:当前选项参数字符串
    2. int optind:argv的当前索引值,索引范围argv[1]到argv[argc-1]
    3. int opterr:这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,默认自动输出其错误信息,一般我们自己初始化其为0,使其不能自动输出错误信息
    4. int optopt——当发现无效选项字符之时,getopt()函数或返回’?‘字符,或返回’:'字符,并且optopt包含了所发现的无效选项字符
  • getopt(int argc, char *argv[], "ab:c:de::")
    /*调用过程分析
       0     1    2  3  4   5   6   7    8   9
    ./test file1 -a -b -c code -d file2 -e file3
    扫描过程中(扫描范围argv[1]到argv[argc-1]),optind是下一个选项的索引, 非选项参数将跳过,同时optind增1。optind初始值为1。当扫描argv[1]时,为非选项参数,跳过直接进行下一次扫描,optind=2;扫描到-a选项时和optstring中的选项字符可以匹配,返回字符a,然后做相关处理,下一个将要扫描的选项是-b,则optind更改为3;扫描到-b选项时,后面有参数(会认为-c为选项b的参数),optind=5,扫描到code非选项跳过optind=6;扫描到-d选项,后面没有参数,optind=7;扫描到file2非选项跳过optind=8;扫描到-e后面本来应该有参数,optind=9但是有空格所以e的参数为空
    */
    /*
    扫描结束后,将选项及参数依次放到argv数组的最左边,非选项参数依次放到argv的最后边
       0    1  2  3  4  5  6     7     8     9
    ./test -a -b -c -d -e file1 code file2 file3
    同时,optind会指向非选项的第一个参数,如上面,optind将指向file1
    */
    
  • 注意:如果调用过程中发现没有选项参数的选项合并在一起,比如-a和-d写成-ad,那么这时候。optind不会加1,但是getopt还会正常扫描

  • 实例程序:

    /********************************************************
    *   Copyright (C) 2017 All rights reserved.
    *
    *   Filename:getopt.c
    *   Author  :YHD
    *   Date    :2017-06-04
    *   Describe:
    *
    ********************************************************/
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char *argv[])
    {
        int opt;
        opterr = 0;
        printf("optind = %d\n", optind);
    
    	while ((opt = getopt(argc, argv, ":asd:")) != -1)
    	{
            switch (opt)
    		{
                case 'a':
    				printf("I am a!\n");
    				break;
    			case 's':
    				printf("I am s!\n");
    				break;
    			case 'd':
    				printf("I am d!\n");
    				printf("input parameter is %s\n", optarg);
    				break;
    			case '?':
    				printf("无效的字符 char is %c\n", optopt);
    				break;
    			case ':':
    				printf("lack of the option parameter!\n");
    				break;
    		}
    		printf("argv[%d] = %s\n", optind, argv[optind]);
    	}
    
        int i;
    	for (i = 0; i < argc; i++)
    	{
    		printf("argv[%d] = %s\n", i, argv[i]);
    	}
    
        printf("argv[%d] = %s\n", optind, argv[optind]);
    
        return 0;
    }
    //方式1
    root@ubuntu:/mnt/hgfs/farsight/work/work_dada/test_dada/getopt# ./getopt -a -s -x -a asdasd -d
    optind = 1
    I am a!
    argv[2] = -s
    I am s!
    argv[3] = -x
    无效的字符 char is x
    argv[4] = -a
    I am a!
    argv[5] = asdasd
    lack of the option parameter!
    argv[7] = (null)
    argv[0] = ./getopt
    argv[1] = -a
    argv[2] = -s
    argv[3] = -x
    argv[4] = -a
    argv[5] = -d
    argv[6] = asdasd
    argv[6] = asdasd
    
    //方式2  
    root@ubuntu:/mnt/hgfs/farsight/work/work_dada/test_dada/getopt# ./getopt -as -x -a asdasd -d
    optind = 1
    I am a!
    argv[1] = -as
    I am s!
    argv[2] = -x
    无效的字符 char is x
    argv[3] = -a
    I am a!
    argv[4] = asdasd
    lack of the option parameter!
    argv[6] = (null)
    argv[0] = ./getopt
    argv[1] = -as
    argv[2] = -x
    argv[3] = -a
    argv[4] = -d
    argv[5] = asdasd
    argv[5] = asdasd
    
    

你可能感兴趣的:(linux应用层)