首页 > 代码库 > 使用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 }
getopttest.c
 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)
makefile

测试一下:

[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