Linux/Unix 编程1: 命令行参数遍历和环境变量

来源:互联网 发布:淘宝网金丝绒太极服 编辑:程序博客网 时间:2024/06/05 20:50
1. POSIX conventions for command line arguments:
    a. -开头的参数表示选项
    b. 如果多个选项都没有参数,那么这些选项可以一起放在-后面
    c. 选项的名称都是单个字符
    d. 有些选项需要参数 比如 ld -o filename
    e. 选项和选项的参数之间的空格可有可无 '-o foo' 和 '-ofoo' 是相同的
    f. 选项一般出现在其他非选项参数之前
    g. 参数'--'用来结束所有的选项,'--'之后的所有参数都被当作非选项参数
    h. '-'被解释成一个普通的非选项参数:传统上用来表示 "从标准输入输出流中输入和输出"
    i. 选项参数可以以任意顺序出现,或出现多次. 选项的解释任务留给提供该选项的特定程序.
    
    GNU在这基础之上提供了long options,形式为"--nam",选项的名称长度一般为1-3.
    '--name=value'

2. 解析程序的参数
   A. Parsing program options using getopt
      1).using the getopt function
      要使用getopt()函数,程序必须包含<unistd.h>,期中包含的下面的变量
      a. int opterr
         if(opterr != 0)
         {
            getopt() prints an error message to the standard error stream if
            {
                1.it encounter an unknown option character(遇到为止的参数选项)
                2.an option with a missing required arguments(有的参数选项没有参数)
            }
         }
         else
         {
             getopt() does not print any messages,but it still returns the character ?
                 to indicate an error.
         }

    b. int optopt
       if(getopt() encounters an unknown option character or an option with a missing required arguments)
            optopt stores that option character
       so you can providing your own diagnostic messages.

    c. int optind
       set by getopt to the index of the next element of the argv array to be processed.
       example : ls -l jiangheng  
                 getopt()后optind 返回2
        
    d. char *optarg
       point to the value of the option(for those options that accept arguments);
       可以通过这个指针来找到带参数选项的参数
    
    e. int getopt(int argc,char *const *argv,const char *options)
       get the next option argument from the argument list;
       the options is a string that specifies the option characters that are "valid" for this program;
       "a:b" 表示 -a 后面要加上一个参数,而 -b 后面不用参数
       "a::" 表示 -a 后面可以加上参数,也可以不加上参数

    B. Example:
    
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    int main(int argc, char **argv)
    {
        int aflag = 0;
        int bflag = 0;
        char *cvalue = NULL;
        int index;
        int c;

        opterr = 0;

        while((c = getopt(argc,argv,"abc:")) != -1)
        {
            switch(c)
            {
                case 'a':
                    aflag = 1;
                    break;
                case 'b':
                    bflag = 1;
                    break;
                case 'c':
                    cvalue = optarg;
                    break;
                case '?':
                    if(optopt == 'c')
                        fprintf(stderr,"Option -%c requires an argument.\n",optopt);
                    else if(isprint(optopt))
                        fprintf(stderr,"Unknown option '-%c'.\n",optopt);
                    else
                        fprintf(stderr,"Unknown option character '\\x%x.\n'",optopt);
                return 1;
                deafault:
                    abort();
            }
        }

        printf("aflag = %d,bflag = %d,cvalue = %s\n",aflag,bflag,cvalue);

        for(index = optind; index < argc ; index++)
            printf("No-option arguments %s\n",argv[index]);
    
        return 0;
    }
    
    D. Parsing Long Options with getopt_long()
    This function is in getopt.h
        a.struct option
        一个这样的结构体用来描述一个long option,getopt_long()种有一个这样的结构体的数组,这个数组的最后一个元素
        为一个阈值全为0的结构体.
        option结构体由以下几个部分构成:
        const char *name : the name of the option, a string
        int has_arg      : whether the option takes an argument
                           no_argument,required_argument,optional_argument;
        int *flag         :
        int val             :
                           The two fields control how to report or act on the option when it occurs.
                           if( flag == NULL )
                                then the val is a value identifes this option.
                           else
                              flag be a address of an int variable which is the flag for this option.
        
        b. int getopt_long(int argc,char *const *argv,const char *shortopts,
                            const struct option *longopts,int *indexptr);

            if(getopt_long() encounters a short option)
                it does the same thing that getopt would do;
            else
            {
                it takes actions based on the flag and val of the long option:

            }
        
        Example:
            

    #include <stdio.h>
    #include <stdlib.h>
    #include <getopt.h>

    /* Flag set by '--verbose' */
    static int verbose_flag;

    int main(int argc,char **argv)
    {
        int c;

        while(1)
        {
            static struct option long_options[]=
            {    
                /* These options set a flag */
                {"verbose",no_argument,    &verbose_flag,1},
                {"brief",  no_argument, &verbose_flag,0},

                /* These options don't set a flag */
                /* we distinguish them by their indices */
                {"add", no_argument, 0, 'a'},
                {"append",no_argument, 0 , 'b'},
                {"delete",required_argument, 0,'c'},
                {"create",required_argument, 0,'d'},
                {"file",  required_argument, 0,'f'},
                {0,0,0,0}
            };

            /* getopt_long stores the option index here */
            int option_index = 0;

            c = getopt_long(argc,argv,"abc:d:f:",long_options,&option_index);

            /* detect the end of the options */
            if(c == -1)
                break;

            switch(c)
            {
                case 0:
                    /* If this option set a flag, do nothing else now. */
                    if(long_options[option_index].flag !=0)
                        break;
                        printf("option %s",long_options[option_index].name);
                    if(optarg)
                        printf(" with arg %s",optarg);
                    printf("\n");
                    break;

                case 'a':
                    puts("option -a\n");
                    break;

                case 'b':
                    puts("option -b\n");
                    break;

                case 'c':
                    printf("option -c with value '%s'\n",optarg);
                    break;

                case 'd':
                    printf("option -d with value '%s'\n",optarg);
                    break;

                case 'f':
                    printf("option -f with value '%s'\n",optarg);
                    break;

                case '?':
                    break;
                deafault:
                    abort();
            }
            
            if(verbose_flag)
                puts("verbose flag is set");

            if(optind < argc)
            {
                puts("non-option ARGV-elements: ");
                while(optind < argc)
                        printf("%s ",argv[optind++]);
                putchar('\n');
            }
        }
        return 0;
    }
    经验总结:
    一开始不是很理解option结构体后面两个域的作用,后来才知道:
    并不是所有的long options都有对应的单个字符的option,像上面的--verbose --brief
    对这样的options将 flag域制定为某个int类型变量的地址,这个变量的值在运行getopt_long()之后
    被设定为val.

3.环境变量:
    环境变量是一把双刃剑:
    a. 优点: it makes it easy for the user to customize the program works without changing how the program is invoked!
    b. 缺点: 如果你写了一个基于特定环境变量的脚本,其他人在不同环境下执行这个脚本时可能会失败.
原创粉丝点击