大家好,又见面了,我是你们的朋友全栈君。
getopt
– 解析命令的可选项
【说明】 getopt
只是一个简单的解析命令可选项的函数,只能进行简单的格式命令解析,格式如下:
1、形如:
cmd [-a][-b]
//对短选项的解析; 2、形如:cmd [-a a_argument][-b b_argument]
//对短选项及短选项的参数解析; 3、形如:cmd [-a[a_argument]]
//选项a的参数也是可选的情况解析 4、形如:cmd [-ab]
// cmd [-a][-b] 这样的形式也能解析
原型:
代码语言:javascript复制#include <unistd.h>
extern char *optarg;
extern int optind, opterr, optopt;
int getopt(int argc, char * const argv[], const char *optstring);
描述:
1、
getopt
函数解析命令行参数,argc
、argv
是调用main
函数时传入的参数。传入的’-‘开始的字符被解析为选项,getopt
一次执行解析出一个option
,如果循环执行,可以将argv
中的全部option
解析出来; 2、在getopt
的执行中,每次进入都会更新option
变量,该变量指向下一个argv
参数; 3、如getopt
返回-1,表示argv[]
中的所有选项被解析出,option
指向第一个非选项的 argument 元素;这里要注意,在getopt
执行过程中会将单独的 argument 交换到argv
数组的后面,option
选项提前,如:cmd -a file1 -b file2
,如果 a/b 均为不带参数的选项,这最终argv
数组变为:cmd -a -b file1 file2
; 4、optstring
指定选项合法的选项,一个字符代表一个选项,在字符后面加一个 ‘:’ 表示该选项带一个参数,字符后带两个 ‘:’ 表示该选项带可选参数(参数可有可无),若有参数,optarg
指向该该参数,否则optarg
为 0; 5、前面说了getopt
会进行argv
顺序的调整,但也可以通过设置optstring
改变它的方式,这里有两种: 1) 如果optstring
的第一个参数是 ‘ ’ 或者POSIXLY_CORRECT
被设置,则getopt
在原argv
的顺序上遇到第一个非选项就返回 -1; 2) 如果optstring
的第一个参数是 ‘-’,则会将所有的非选项当选项处理,并且返回 1,用字符代码 1 表示该选项; 6、如果getopt
不能识别一个选项字符,它会打印一个错误消息到stderr
上,并将该字符存放到optopt
中,返回 ‘?’;调用程序可以设置opterr=0
设置不打印错误信息;注意:要使能打印错误信息,optstring
的第一个字符(或者在第一个字符是 /- 之后)不能是 ‘:’,否则也不会打印错误; 7、如果optstring
中指定了option
需要参数,但在命令行没有参数,那么getopt
将返回 ‘?’,如果在optstring
的第一个字符(或者在第一个字符是 /- 之后)是 ‘:’,那么将返回 ‘:’; 8、如果在选项中有 “–”,并且前后是空格,其含义是强制终止getopt
的继续执行,返回 -1,这个可以用来做一些特殊的处理;
返回值:
1、返回类型为
int
,这个在编程的时候要注意,因为返回值类型范围要包含 -1,很容易返回值接收定义为char
,但在一些系统中char
是无符号的,将导致程序错误; 2、当传入的argv
中的选项全部被解析,getopt()
返回 -1,这也是getopt
进行选项解析的循环截至条件; 3、如果argv
中解析出optstring
中描述的选项字符,则返回该字符,如果该选项指定了参数,则全局变量optarg
指向该参数; 4、如果getopt
遇到一个非optstring
指定的选项字符,这表示该选项是未识别的,返回 ‘?’,并且将该选项存放到全局变量optopt
中; 5、如果optstring
指定了选项必须带参数,但传入的相应option
丢失了参数,返回值依赖于optstring
的第一个字符,若第一个字符是 ‘:’,返回 ‘:’,否则返回 ‘?’;由于非法的选项返回也是 ‘?’,所以常常optstring
的第一个字符指定为 ‘:’;同时将该选项存放到全局变量optopt
中;
测试例程:
代码语言:javascript复制#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] %sn", i, argv[i]);
}
printf ("n");
while ((ret = getopt(argc, argv, ":a:b::c")) != -1)
{
switch (ret) {
case 'a':
printf ("option: %c argv: %sn", ret, optarg);
break;
case 'b':
if (optarg)
printf ("option: %c argv: %sn", ret, optarg);
else
printf ("option: %c no argumentn", ret);
break;
case '?':
printf ("encountered a unrecognized option: %c, argv: %sn", optopt, argv[optind - 1]);
break;
case ':':
printf ("option: %c missing argumentn", optopt);
break;
default:
printf ("option: %cn", ret);
break;
}
}
printf ("noptind: %dnn", optind);
for (i=optind; i>0 && i<argc; i )
printf ("argv[%d] %sn", i, argv[i]);
printf ("n");
for (i=0; i<argc; i )
printf ("argv[%d] %sn", i, argv[i]);
return 0;
}
然后我们运行测试例程,自己根据前面的描述进行一些分析:
代码语言:javascript复制root@ParseCmdLine:./parse_cmdline -axxx -byyy
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
option: a argv: xxx
option: b argv: yyy
optind: 3
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
root@ParseCmdLine:./parse_cmdline -a xxx -b yyy
argv[0] ./parse_cmdline
argv[1] -a
argv[2] xxx
argv[3] -b
argv[4] yyy
option: a argv: xxx
option: b no argument
optind: 4
argv[4] yyy
argv[0] ./parse_cmdline
argv[1] -a
argv[2] xxx
argv[3] -b
argv[4] yyy
从这个可以看出,带参数的option参数可以紧跟,也可以中间有空格;
代码语言:javascript复制root@ParseCmdLine:./parse_cmdline -axxx -b yyy -c
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -b
argv[3] yyy
argv[4] -c
option: a argv: xxx
option: b no argument
option: c
optind: 4
argv[4] yyy
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -b
argv[3] -c
argv[4] yyy
root@ParseCmdLine:./parse_cmdline -axxx -byyy -c
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
argv[3] -c
option: a argv: xxx
option: b argv: yyy
option: c
optind: 4
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
argv[3] -c
从这里可以看出,对于 -b
是可跟参数也可不跟参数的,参数必须紧跟,中间不能有空格。同时还可以看出:在有 argument在 argv
中,最后出现了 argv[]
元素位置变化,选项前移了,而参数后移;
root@ParseCmdLine:./parse_cmdline -x
argv[0] ./parse_cmdline
argv[1] -x
encountered a unrecognized option: x, argv: -x
optind: 2
argv[0] ./parse_cmdline
argv[1] -x
root@ParseCmdLine:./parse_cmdline -a
argv[0] ./parse_cmdline
argv[1] -a
option: a missing argument
optind: 2
argv[0] ./parse_cmdline
argv[1] -a
这里可以看出未识别的 option
,和丢失参数的 option
情况;
// 修改代码while ((ret = getopt(argc, argv, "a:b::c")) != -1)
root@ParseCmdLine:./parse_cmdline -x
argv[0] ./parse_cmdline
argv[1] -x
./parse_cmdline: invalid option -- x
encountered a unrecognized option: x, argv: -x
optind: 2
argv[0] ./parse_cmdline
argv[1] -x
// 修改代码while ((ret = getopt(argc, argv, " a:b::c")) != -1)
root@ParseCmdLine:./parse_cmdline -x xxxx -ayyyy -bzzz kkkk
argv[0] ./parse_cmdline
argv[1] -x
argv[2] xxxx
argv[3] -ayyyy
argv[4] -bzzz
argv[5] kkkk
./parse_cmdline: invalid option -- x
encountered a unrecognized option: x, argv: -x
option: a argv: yyyy
option: b argv: zzz
optind: 4
argv[4] xxxx
argv[5] kkkk
argv[0] ./parse_cmdline
argv[1] -x
argv[2] -ayyyy
argv[3] -bzzz
argv[4] xxxx
argv[5] kkkk
这块代码说明了 optstring
第一个字符的作用,剩余的其他功能读者自己分析;
root@ParseCmdLine:./parse_cmdline -axxx -- -byyyy
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] --
argv[3] -byyyy
option: a argv: xxx
optind: 3
argv[3] -byyyy
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] --
argv[3] -byyyy
这一块说明了 “–” 的应用;
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/133444.html原文链接:https://javaforall.cn