首页 > 代码库 > 使用getopt函数对命令行短形参进行处理
使用getopt函数对命令行短形参进行处理
今天,在看man 9 style时见到了用来处理命令行短形参getopt函数,很是诧异 —— 要知道,我处理命令行参数都是用手动的!于是我如获至宝,赶紧学习学习。
getopt的原型被放在unistd.h中,它的原型是这样的:int getopt(int argc, char * const argv[], const char *optstring)
这里的argc,argv就是main函数的形参,需要调用是只要把main形参给传过去就ok了。后面的optstring是一个集合,包括了所有可能的短参数的结果,它的语法是这样的:
1. 单个字符
表示没有形参值的短形参(所谓的短形参就比如说gcc -c foo.c -o foo这里的"-c"就是一个没有形参值的短形参,后面的"-o foo"就是有形参值的短形参。而--help之类的就是长形参,可以用getopt_long函数来处理),这种不带值的形参可以连写,比如"foo -c -d -e"就可以写成"foo -cde",getopt照样可以识别
2. 单个字符加一个‘:‘符号
表示必须带值的短形参。比如在"gcc -c -o foo foo.txt"中如果想要读取"-o foo"就可以写"o:"。该参数(在这里是foo)的指针赋给optarg。(这个特性是Linux C的扩展)
3. 单个字符加两个‘:‘符号
表示可选值的短形参。比如在"gcc -O3"中就存在一个可选值短形参-O,它的值为3。该参数(在这里是3)的指针同样赋给optarg。
我写了小程序,使用getopt函数根据形参对一个文本进行查找。
1 #include <err.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <unistd.h> 5 6 static void usage(char *); 7 8 int 9 main(int argc, char **argv) 10 { 11 int ch; 12 int usageflag = 0; 13 char *source = NULL; 14 char *match = NULL; 15 char *progname = argv[0]; 16 17 while ((ch = getopt(argc, argv, "hs:m:")) != -1) 18 switch (ch) { 19 case ‘s‘: 20 source = optarg; 21 break; 22 case ‘m‘: 23 match = optarg; 24 break; 25 case ‘h‘: 26 usageflag = 1; 27 break; 28 default: 29 warn("undefined arg %c\n", ch); 30 break; 31 } 32 33 if (usageflag != 1 && source != NULL && match != NULL) 34 printf("%s\n", strstr(source, match)); 35 else 36 usage(progname); 37 38 return 0; 39 } 40 41 static void 42 usage(char *progname) 43 { 44 warnx("Usage: %s [-h] -s source -m match", progname); 45 }
1 src.c=getopttest.c 2 cflags=-O3 3 target.exe=getopttest 4 cc=gcc 5 6 all: $(target.exe) 7 8 $(target.exe): 9 $(cc) $(src.c) -o $(target.exe) $(cflags) 10 11 .PHONY: dist clean 12 13 ###################################################### 14 15 source.d=. 16 target.tar=getopt.tar 17 18 dist: $(target.tar) 19 20 $(target.tar): clean 21 -rm *~ 22 tar cf $(target.tar) $(source.d) 23 24 ###################################################### 25 26 clean: 27 -rm $(target.exe) $(target.tar)
测试一下:
[louis@debian ~/getopt]$ make clean
rm getopttest
[louis@debian ~/getopt]$ make
gcc getopttest.c -o getopttest -O3
[louis@debian ~/getopt]$ ./getopttest -h
getopttest: Usage: ./getopttest [-h] -s source -m match
[louis@debian ~/getopt]$ ./getopttest
getopttest: Usage: ./getopttest [-h] -s source -m match
[louis@debian ~/getopt]$ ./getopttest -s "GNU IS NOT UNIX" -m "UNIX"
UNIX
[louis@debian ~/getopt]$ ./getopttest -s "GNU IS NOT UNIX" -m "GNU"
GNU IS NOT UNIX
[louis@debian ~/getopt]$ ./getopttest -s "GNU IS NOT UNIX" -m "IS"
IS NOT UNIX
[louis@debian ~/getopt]$ ./getopttest -s "GNU IS HORRIBLE" -m "IS"
IS HORRIBLE
[louis@debian ~/getopt]$ make clean
rm getopttest