今天,在看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
测试一下:
[[email protected] ~/getopt]$ make clean
rm getopttest
[[email protected]
~/getopt]$ make
gcc getopttest.c -o getopttest -O3
[[email protected]
~/getopt]$ ./getopttest -h
getopttest: Usage: ./getopttest [-h] -s source -m
match
[[email protected] ~/getopt]$ ./getopttest
getopttest: Usage:
./getopttest [-h] -s source -m match
[[email protected] ~/getopt]$ ./getopttest -s
"GNU IS NOT UNIX" -m "UNIX"
UNIX
[[email protected] ~/getopt]$ ./getopttest -s
"GNU IS NOT UNIX" -m "GNU"
GNU IS NOT UNIX
[[email protected] ~/getopt]$
./getopttest -s "GNU IS NOT UNIX" -m "IS"
IS NOT UNIX
[[email protected]
~/getopt]$ ./getopttest -s "GNU IS HORRIBLE" -m "IS"
IS
HORRIBLE
[[email protected] ~/getopt]$ make clean
rm getopttest