经常接触Linux的同学应该有这样的体验,当遇到一个不会使用的命令时通常敲一下xCmd -h或者xCmd --help来获取命令提示,例如tcpdump命令或者iptables命令,像这样的选项仅仅是获取提示帮助的,实现起来不会很难,但如果考虑到一些复杂的选项,比如说下面这条命令:

iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

这个命令包含多个选项,且选项或许还带有参数,如果完全由自己进行实现的话,可以是可以的,但是难免要花费一些功夫,尤其是在已有现成的实现情况下,函数getopt和getopt_long就是专门用来解析命令行参数的,一个是用来处理短选项(-开头)一个长选项(--开头)功能强大易用,简单方便,妈妈再也不担心我写错代码了^_^。

先看下getopt函数定义和声明:

#include <unistd.h>

int getopt(int argc, char * const argv[],
           const char *optstring);

extern char *optarg;
extern int optind, opterr, optopt;

给定了命令参数的数量 (argc)、指向这些参数的数组 (argv) 和选项字符串 (optstring) 后,getopt() 将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有识别到的选项,将返回 -1,此任务就完成了。

getopt() 所设置的全局变量包括:

optarg——指向当前选项参数(如果有)的指针。
optind——再次调用 getopt() 时的下一个 argv 指针的索引。
optopt——最后一个已知选项。

对于每个选项,选项字符串 (optstring) 中都包含一个对应的字符。具有参数的选项(如示例中的 -l 和 -o 选项)后面跟有一个 : 字符。可以重复调用 getopt(),直到其返回 -1 为止;

示例:

#include <stdio.h>
#include <unistd.h>

/* 处理abch四个选项,其中bc含有参数 */
static const char *optString = "ab:c:h";

void main(int argc, char **argv)
{
    int opt;
    opt = getopt( argc, argv, optString );
    while( opt != -1 ) {
        switch( opt ) {
            case 'a':
                printf("receive a \n");
                break;
                 
            case 'b':
                printf("receive b with argument :%s \n", optarg);
                break;
                 
            case 'h':
                printf("Usage : help \n");
                break;
                                  
            default:
                printf("*** can't recognize input char!!! \n");
                break;
        }
         
        opt = getopt( argc, argv, optString );
    }
    return ;
}

 c语言命令行选项处理函数getopt和getopt_long() 函数使用_linux

getopt只能处理带一个 ‘-’的选项,如果是含有两个‘--’则可以使用getopt_long了,


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

struct option {
    char *name;
    int has_arg;
    int *flag;
    int val;
};

name 成员是指向长选项名称(带两个短横线)的指针。has_arg 成员设置为 no_argument、optional_argument, 或 required_argument(均在 getopt.h 中定义)之一,
以指示选项是否具有参数。如果 flag 成员未设置为 NULL,在处理期间遇到此选项时,
会使用 val 成员的值填充它所指向的 int 值。如果 flag 成员为 NULL,在 getopt_long()
 遇到此选项时,将返回 val 中的值。

 用例:

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

static const char *optString = "h";

static int do_init = 0;

/* 收到init参数会将1的值赋值给do_init,
 * 收到name或者age返回字符,这里可以返回数字
 */
static const struct option longOpts[] = {
    { "init", no_argument, &do_init, 1 },
    { "name", required_argument, NULL, 'n' },
    { "age", required_argument, NULL, 'a' },
    { 0, 0, 0, 0 }
};


void main(int argc, char **argv)
{
    int longIndex, opt;
    
    opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
    while( opt != -1 ) {
        switch( opt ) {
            case 0 :
                printf("do_init : %d\n", do_init);
                break;
            case 'h':
                printf("Usage : --init --name xx \n");
                break;                   
            case 'n':
                printf("input name : %s\n", optarg);
                break;                                    
            case 'a':
                printf("input age : %s\n", optarg);
                break; 

            default:
                printf("*** fail, unrecognized option ***\n");
                break;
        }
         
        opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
    }

    return ;
}

c语言命令行选项处理函数getopt和getopt_long() 函数使用_getopt_02 

参考资料:

1. https://linux.die.net/man/3/getopt

2. https://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html