一个典型的UNIX命令形式如下:
command [ optinds ]arguments
多个选项可以在一个单独的连字符后归组在一起,组中最后一个选项可能带有参数,故以下命令是等同的:
$grep -l -i -f patterns *.c
$grep -lif patterns *.c
$grep -lifpatterns *.c
在这些命令中-l
和-i
选项没有参数,而-f
选项将字符串pattern
当作它的参数;
#include <unistd.h>
extern int optind, opterr, optopt;
extern char *optarg;
int getopt(int argc, char *const argv[], const char *optstring);
- 通过连续调用
getopt()
解析命令行,每次调用时全局变量optind
都得到更新,其中包含着参数列表argv
中未处理的下一个元素的索引,在首次调用getopt()
函数前optind
变量会自动设置为1
; getopt()
函数的返回值为int,不能将其赋值给char
类型变量,因为char
类型在无符号整数的系统上char类型同-1
之间的比较不会成功, -1表示目前没有更多的选项可解析了 ;- 如果选项有带参数,
getopt()
函数就把全局变量optarg
设为指向这个参数;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
extern char *optarg;
extern int optind, opterr, optopt;
int i;
int ret;
for (i=0; i<argc; i++)
{
printf ("argv[%d] %s\n", i, argv[i]);
}
printf ("\n");
while ((ret = getopt(argc, argv, "+:a:b::c:d:")) != -1)
{
switch (ret) {
case 'a':
printf ("option: %c argv: %s\n", ret, optarg);
break;
case 'b':
if (optarg)
printf ("option: %c argv: %s\n", ret, optarg);
else
printf ("option: %c no argument\n", ret);
break;
case 'c':
printf ("option: %c argv: %s\n", ret, optarg);
break;
case '?':
printf ("encountered a unrecognized option: %c, argv: %s\n", optopt, argv[optind - 1]);
break;
case ':':
printf ("option: %c missing argument\n", optopt);
break;
default:
printf ("option: %c\n", ret);
break;
}
}
printf ("\noptind: %d\n\n", optind);
for (i=optind; i>0 && i<argc; i++)
printf ("argv[%d] %s\n", i, argv[i]);
printf ("\n");
for (i=0; i<argc; i++)
printf ("argv[%d] %s\n", i, argv[i]);
return 0;
}
- 在
getopt()
执行过程中会将单独的argument
交换到argv
数组的后面,option
选项提前,如:cmd -a file1 -b file2
,如果a/b
均为不带参数的选项,这最终argv
数组变为:cmd -a -b file1 file2
,可以通过在第一个字母前使用符号+
,如果同时禁止错误消息就需要再添加符号:
,即同时添加+:
(顺序不能乱); optstring
指定选项合法的选项,一个字符代表一个选项,在字符后面加一个冒号表示该选项带一个参数,字符后带两个冒号表示该选项带可选参数(参数可有可无),- 如果optstring中指定了option需要参数,但在命令行没有参数,那么getopt将返回’?’,