Linux getopt函数处理传入参数

1、Linux传入参数处理

在介绍使用getopt函数处理应用程序传入参数前,先来看一下Linux环境下编写的应用程序是如何处理传入的参数的

Linux环境编写应用程序时,main函数一般会有两个参数,用于描述执行应用程序时传入的参数,书写形式如下:

int main(int argc, char *argv[])
  • argc:表示传入参数的个数
  • argv:指针数组,每一项存放一个传入参数字符串的地址

在shell中启动这个应用程序,shell接受用户输入命令行,将命令行分解成单词,然后把这些单词放入到一个数组,操作系统将这个存放单词数组的长度和数组作为参数传递给了main函数。因此,实际情况下,argv[0]指向的一定是运行当前应用程序的全路径名称,argv[1]~argv[argc-1]指向的才是传入参数,实际传入参数的个数为argc-1

例如有一个名为hello_world应用程序,在shell中按照 "./hello_world 3" 执行该程序,此时,argc = 2,argv[0]指向的是 "./hello_world" 字符串存放地址,argv[1]指向的才是传入参数 "3" 字符串存放地址

显然,我们可以在main函数内自己编写程序,通过解析argc,argv参数来获取执行应用程序所传入的参数。但对于Linux这种广泛使用的操作系统,它已经在库函数中为用户提供了用于命令行参数解析的函数,我们直接调用这些函数,便可轻松的解析各种命令行参数模式

这里所讲的getopt函数,就是标准库中实现的一个用于解析命令行参数的函数,它支持需要关联值和不需要关联值的选项,而且简单易用。

(所谓的需要关联值的选项,以gcc编译器为例子,gcc的-o选项表示输出可执行程序名称,这个后面就需要跟一个名称才能正常使用,后面一个参数就是-o命令的关联值;所谓的不需要关联值,以ls命令为例子, ls的-l命令表示列出当前目录所有文件,这个后面不需要跟一些其他信息,这种被称作不需要关联值的选项)

2、getopt函数的原型

getopt函数有三个参数,函数的原型如下:

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

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

getopt函数本质上其实就是对main函数传入的argc和argv参数进行处理,它将传递给程序的main函数的argc和argv作为参数,同时接受一个选项指定字符串optstring。optstring字符串告诉getopt哪些选项可用,以及它们是否有关联值。

optstring是一个字符串列表,每个字符代表一个单字符选项。如果一个字符后面紧跟一个冒号(:),则表示一个该选项有一个关联值作为下一个参数。

例如:getopt(argc, argv, "if:l")

它允许-i、-f、-l作为参数,其中-f选项后要紧跟一个参数,也就是它的关联值。这里参数的传递可以不按照optstring字符串列表写入的顺序来传

getopt的返回值是argv数组中的下一个选项字符,循环调用getopt可以依次得到argv中每一个选项。函数的处理行为如下:

  • 如果选项处理完毕,返回值为-1,循环遇到-1,可以退出
  • 如果选项有一个关联值,全局变量optarg指向这个值
  • 如果遇到不在optstring中选项,getopt返回一个问号(?),并将无法识别选项存放到全局变量optopt,有些getopt版本会在遇到未知选项时打印错误信息
  • 如果选项要求有关联值,但是用户没传入一个关联值,默认情况下getopt通常返回一个问号(?)。我们可以将选项字符串的第一个字符设置成冒号,这个没传入关联值时,返回的是冒号(:)而不是问号(?)

optind表示下一个待处理参数的索引,getopt利用它来记录自己的进度,一般情况下在程序中很少用到

3、函数的使用

编写一个简单的例子,来演示getopt函数使用

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


int main(int argc, char *argv[])
{
    int res;

    while((res = getopt(argc, argv, ":io:l")) != -1)
    {
        switch(res)
        {
            case 'i':
            case 'l':
                    printf("option: %c\n", res);
                    break;
                    
            case 'o':
                    printf("option: %c %s\n", res, optarg);
                    break;
                    
            case ':':
                    printf("option need a value\n");
                    break;
                    
            case '?':
                    printf("unknown option: %c\n", optopt);
                    break;
                    
            default:
                    break;
        }
    }
}

main函数内使用getopt函数对传入参数进行解析,支持参数有-i、-o、-l,其中-o参数后要有一个关联值。这里optstring参数的第一个字符设置成冒号,是用来分辨输入-o,但没传入关联值情况,这种情况(:)被返回

如果传入-i、-l参数,打印参数信息

如果传入-o参数,打印参数信息和关联值信息

如果传入-o参数,并没传入关联值,打印出提示信息

如果传入无效参数时,打印出不识别提示信息

4、小结

调用getopt函数可以方便的处理我们程序中传入的不同参数,它按照我们指定的方式来解析main函数中传入的argc和argv参数,并返回选项字符。支持的参数在getopt的optstring参数指定,通过参数后面冒号(:)的有无来表示该参数后面是否需要紧跟关联值信息。但getopt函数也有自己的局限性,它仅支持的是单字符参数,如果想接受比单字符选项含义更明确的参数时,就不适用了。不过,如果你有这种需求,可以去研究下C库中getopt函数的另一个增强版本——getopt_long,它接受以下划线(--)开始的长参数

上一篇:浅析linux的命令行的参数getopt_long函数


下一篇:python命令行-getopt模块