平时写程序时,有时需要对命令行参数进行处理。在接触本文所涉及的内容前,我们可能想到的方法是顺序提取命令行参数,进行顺序判断处理;然而,这种方法相当不灵活,尤其是在遇到带有可选参数的情况时,很难处理。为此,Linux提供了如下接口进行命令行参数的处理:
#include <unistd.h> int getopt(int argc, char * const argv[],const char *optstring); extern char *optarg; extern int optind, opterr, 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);
optarg; //指向当前选项参数(如果有)的指针 optind, //再次调用 getopt() 时的下一个 argv 指针的索引 opterr, //指定getopt、getopt_long、getopt_long_only是否在遇到错误时将错误输出到标准输出流 optopt; //最后一个未知选项
int getopt(int argc, char * const argv[],const char *optstring);argc和argv与main函数的两个参数相匹配的
#include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { int opt; char *optstring = "a:b::cd:"; while ((opt = getopt(argc, argv, optstring)) != -1) { printf("opt = %c\n", opt);<span style="white-space:pre"> </span> //输出选项名称 printf("optarg = %s\n", optarg); //输出选项后接的参数 printf("optind = %d\n", optind); //输出当前命令行参数下一个参数的下标 printf("argv[optind-1] = %s\n\n", argv[optind-1]); // } return 0; }测试
windeal@ubuntu:Test$ ./a.out -a 100 -b200 -b -c -d 300 opt = a optarg = 100 optind = 3 argv[optind-1] = 100 opt = b optarg = 200 optind = 4 argv[optind-1] = -b200 opt = b optarg = (null) optind = 5 argv[optind-1] = -b opt = c optarg = (null) optind = 6 argv[optind-1] = -c opt = d optarg = 300 optind = 8 argv[optind-1] = 300 windeal@ubuntu:Test$
getopt_long相当于getopt的拓展,getopt_long支持长选项参数(即选项不是单个字符)。
getopt_long其原型如下:
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);除了与getopt相同的三个参数外,getopt_long还带有参数longopts,和longindex。
longindex表示当前长参数在longopts中的索引值
longopts类型定义如下
struct option { const char *name; int has_arg; int *flag; int val; };
required_argument(或者是1)时 ——参数输入格式为:--参数 值 或者 --参数=值。
optional_argument(或者是2)时 ——参数输入格式只能为:--参数=值。
#include <stdio.h> #include <unistd.h> #include <getopt.h> #define VAL1 0 #define VAL2 1 #define VAL3 2 int main(int argc, char* argv[]) { int opt; int this_option_optind = optind ? optind : 1; char *optstring = "a:b::cd:"; struct option long_options[] = { {"lopt1", no_argument, 0, VAL1}, {"lopt2", required_argument, 0, VAL2}, {"lopt3", optional_argument, 0, VAL3}, {"lopt4", no_argument, 0, VAL1}, {0,0,0,0} }; int option_index = 0; while ((opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1) { switch(opt) { case VAL1: case VAL2: case VAL3: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case 'a': case 'b': case 'c': case 'd': printf("opt = %c\n", opt); //输出选项名称 printf("optarg = %s\n", optarg); //输出选项后接的参数 printf("optind = %d\n", optind); //输出当前命令行参数下一个参数的下标 printf("argv[optind-1] = %s\n\n", argv[optind-1]); // default: exit(-1); break; } } return 0; }
测试结果:
windeal@ubuntu:Test$ ./a.out --lopt1 --lopt2 23 --lopt3=33 --lopt4 -a 100 option lopt1 option lopt2 with arg 23 option lopt3 with arg 33 option lopt4 opt = a optarg = 100 optind = 8 argv[optind-1] = 100 windeal@ubuntu:Test$ vim test.c
getopt_long_only与getopt_long参数表和功能基本相同,主要差别的地方在于长选项参数的解析。
在getopt_long中,长选项参数需要由双横杠开始,即--name, 而-name会被解析成-n,-a,-m和-e在optstring中匹配
在getopt_long_only中,--name和-name都被解析成长选项参数。