在学习Unix/Linux编程实践教程时,编写练习一些linux命令,需要对命令行参数进行解析,从而接触到getopt系列函数:
1. getopt()
2. getopt_long()
3.getopt_long_only()
总结如下:
Parse command-line options
NAMEgetopt, getopt_long, getopt_long_only, optarg, optind, opterr, optopt - Parse command-line optionsSYNOPSIS#include <unistd.h>int getopt(int argc, char * const argv[],const char *optstring);extern char *optarg;extern int optind, opterr, optopt;#include <getopt.h>int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);
1. getopt()函数
函数说明
getopt()用来分析命令行参数。参数argc和argv是由main()传递的参数个数和内容。参数optstring 则代表欲处理的选项字符串。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。
optopt:如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,
opterr:将全域变量opterr设为0,getopt()不打印出错信息
optarg:选项的参数指针
短参数的定义
getopt()使用optstring所指的字串作为短参数列表,“lba:d::”这就是一个短参列表,命令行使用时应加上“-”(即“-l”),
其中短参数在getopt定义里分为三种:
- 不带值的参数,它的定义即是参数本身。
- 必须带值的参数,它的定义是在参数本身后面再加一个冒号。
- 可选值的参数,它的定义是在参数本身后面加两个冒号 。
在实际调用中,’-l -b -a ty -d’, ‘-lb -a ty -ddvalue’, ‘-lb -a ty -ddvalue’都是合法的。这里需要注意三点:
- 不带值的参数可以连写,-l 和-b,它们可以-l -b分开写,也可以-lb或-bl连写。
- 参数不分先后顺序
- 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误,必选参数的值和参数之间可有空格也可没有。
optind
变量optind 是argv中要被处理的下一个元素的索引。初始值为1,最大值为optstring中定义的选项个数(有可选(::)参数的算一个;必选(:)参数选项和参数之间没空格算一个,有空格算两个)加 1 ,getopt会遍历argv,每次调用后都会让optind指向下一个option在argv中的索引,每次optind移动多少取决于optstring中的字段:
- 遇到”x”,选项不带参数,optind += 1
- 遇到“x:”,带参数的选项,optarg = argv[optind + 1], optind += 2
- 遇到“x::”,可选参数,属于#1和#2之一,GNU扩展实现。
如果一切顺利,最后optind应该指向第一个非option参数,如果optind >= argc,说明没有已经没有参数了。如果遇到不认识的参数或丢失的参数,另外两个全局变量“opterr, optopt”就派上用场了,剩下的就看文档和源代码吧。
返回值
getopt()每次调用会逐次返回命令行传入的参数。
当没有参数的最后的一次调用时,getopt()将返回-1。
当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'。
当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?' 。
#include <unistd.h>#include <stdlib.h>#include <stdio.h>int main(int argc, char *argv[]){int flags, opt;int nsecs, tfnd;nsecs = 0;tfnd = 0;flags = 0;while ((opt = getopt(argc, argv, "nt:")) != -1) {switch (opt) {case 'n':flags = 1;break;case 't':printf("-t %s\n",optarg);tfnd = 1;break;default: /* '?' */fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",argv[0]);exit(EXIT_FAILURE);}}printf("flags=%d; tfnd=%d, optind=%d, argc=%d\n", flags, tfnd, optind,argc);if (optind >= argc) {fprintf(stderr, "Expected argument after options\n");exit(EXIT_FAILURE);}printf("argv[optind] name argument = %s\n", argv[optind]);exit(EXIT_SUCCESS);}[ty@ty argument]$ ./a.out -tty name-t tyflags=0; tfnd=1, optind=2, argc=3argv[optind] name argument = name[ty@ty argument]$ ./a.out -t ty name-t tyflags=0; tfnd=1, optind=3, argc=4argv[optind] name argument = name
2. getopt_long()函数
getopt_long支持长选项的命令行解析,函数中的参数argc和argv通常直接从main()的两个参数传递而来
int getopt_long(int argc,char * const argv[],const char *optstring,const struct option *longopts,int *longindex)getopt_long支持长选项的命令行解析:
参数argc和argv通常直接从main()的两个参数传递而来。
optstring是选项参数和getopt函数一致;
longopts指定长选项,是个结构体指针,结构体如下:struct option {const char *name; //name表示的是长参数名int has_arg;int *flag; //用来决定,getopt_long()的返回值到底是什么。如果flag是null,则函数会返回与该项option匹配的val值int val; //和flag联合决定返回值}has_arg有3个值:
- no_argument(或者是0),表示该参数后面不跟参数值
- required_argument(或者是1),表示该参数后面一定要跟个参数值
- optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值
在实际情况中,我们还希望每个长选项都对应一个短选项,此时在option结构中,只需将flag设置为NULL,并将val设置为长选项所对应的短选项字符即可。
实例如下:
#include <stdio.h> /* for printf */#include <stdlib.h> /* for exit */#include <getopt.h>int main(int argc, char **argv){int c;int digit_optind = 0;while (1) {int this_option_optind = optind ? optind : 1;int option_index = 0;static struct option long_options[] = {{"add", 1, 0, 0},{"append", 0, 0, 0},{"delete", 1, 0, 0},{"verbose", 0, 0, 0},{"create", 1, 0, 'c'},{"file", 1, 0, 0},{0, 0, 0, 0}};c = getopt_long(argc, argv, "abc:d:012",long_options, &option_index);if (c == -1)break;switch (c) {case 0:printf("option %s", long_options[option_index].name);if (optarg)printf(" with arg %s", optarg);printf("\n");break;case '0':case '1':case '2':if (digit_optind != 0 && digit_optind != this_option_optind)printf("digits occur in two different argv-elements.\n");digit_optind = this_option_optind;printf("option %c\n", c);break;case 'a':printf("option a\n");break;case 'b':printf("option b\n");break;case 'c':printf("option c with value '%s'\n", optarg);break;case 'd':printf("option d with value '%s'\n", optarg);break;case '?':break;default:printf("?? getopt returned character code 0%o ??\n", c);}}if (optind < argc) {printf("non-option ARGV-elements: ");while (optind < argc)printf("%s ", argv[optind++]);printf("\n");}exit(EXIT_SUCCESS);}
3. getopt_long_only()函数
该函数和getopt_long功能基本相同,只不过它还可以支持一个“-”的长选项(即 “-name”)
编写的一个类find命令的程序sfind,使用getopt_long_only解析参数选项
https://github.com/ty92/sfind
本文详细介绍了Unix/Linux编程中的getopt、getopt_long和getopt_long_only函数,包括它们的功能、参数解释、短参数定义、optind变量、返回值等关键信息。通过实例展示了如何在实际调用中正确使用这些函数,提供了丰富的编程实践指导。
2904

被折叠的 条评论
为什么被折叠?



