getopt被用来解析命令行选项参数。html
#include <unistd.h> extern char *optarg; //选项的参数指针 extern int optind, //下一次调用getopt的时,从optind存储的位置处从新开始检查选项。 extern int opterr, //当opterr=0时,getopt不向stderr输出错误信息。 extern int optopt; //当命令行选项字符不包括在optstring中或者选项缺乏必要的参数时,该选项存储在optopt中,getopt返回'?’、 int getopt(int argc, char * const argv[], const char *optstring);
调用一次,返回一个选项。 在命令行选项参数再也检查不到optstring中包含的选项时,返回-1,同时optind储存第一个不包含选项的命令行参数。shell
首先说一下什么是选项,什么是参数。数组
字符串optstring能够下列元素,函数
单个字符,表示选项,工具
单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。测试
单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。ui
getopt处理以'-’开头的命令行参数,如spa
optstring="ab:c::d::",命令行为getopt.exe -a -b host -ckeke -d haha
在这个命令行参数中,-a和-h就是选项元素,去掉'-',a,b,c就是选项。host是b的参数,keke是c的参数。但haha并非d的参数,由于它们中间有空格隔开。命令行
还要注意的是默认状况下getopt会从新排列命令行参数的顺序,因此到最后全部不包含选项的命令行参数都排到最后。设计
如 getopt.exe -a ima -b host -ckeke -d haha, 都最后命令行参数的顺序是: -a -b host -ckeke -d ima haha
若是optstring中的字符串以'+'加号开头或者环境变量POSIXLY_CORRE被设置。那么一遇到不包含选项的命令行参数,getopt就会中止,返回-1。
unistd.h中的全局变量示例以下
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv) { int result; opterr = 0; //使getopt不行stderr输出错误信息 while( (result = getopt(argc, argv, "ab:c::")) != -1 ) { switch(result) { case 'a': printf("option=a, optopt=%c, optarg=%s\n", optopt, optarg); break; case 'b': printf("option=b, optopt=%c, optarg=%s\n", optopt, optarg); break; case 'c': printf("option=c, optopt=%c, optarg=%s\n", optopt, optarg); break; case '?': printf("result=?, optopt=%c, optarg=%s\n", optopt, optarg); break; default: printf("default, result=%c\n",result); break; } printf("argv[%d]=%s\n", optind, argv[optind]); } printf("result=-1, optind=%d\n", optind); //看看最后optind的位置 for(result = optind; result < argc; result++) printf("-----argv[%d]=%s\n", result, argv[result]); //看看最后的命令行参数,看顺序是否改变了哈。 for(result = 1; result < argc; result++) printf("\nat the end-----argv[%d]=%s\n", result, argv[result]); return 0; } unistd里有个 optind 变量,每次getopt后,这个索引指向argv里当前分析的字符串的下一个索引,所以 argv[optind]就能获得下个字符串,经过判断是否以 '-'开头就可。下面是个测试程序 #include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { int tmp = 4; while( (tmp = getopt(argc, argv, "abck")) != -1 ) { printf("-%c\t", tmp); int opt = optind ; while( opt < argc ) { if ( argv[opt][0] != '-' ) { printf("%s\t", argv[opt]); opt ++; } else break; } printf("\n"); } getchar(); } 函数说明 getopt()用来分析命令行参数。参数argc和argv是由main()传递的参数个数和内容。参数optstring 则表明欲处理的选项字符串。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。若是选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。若是getopt()找不到符合的参数则会印出错信息,并将全域变量getopt设为“?”字符,若是不但愿getopt()印出错信息,则只要将全域变量opterr设为0便可。 返回值 若是找到符合的参数则返回此参数字母,若是参数不包含在参数optstring 的选项字母则返回“?”字符,分析结束则返回-1。
#include<stdio.h> #include<unistd.h> int main(int argc,char **argv) { int ch; opterr = 0; while((ch = getopt(argc,argv,”a:bcde”))!= -1) switch(ch) { case ‘a’: printf(“option a:’%s’\n”,optarg); break; case ‘b’: printf(“option b :b\n”); break; default: printf(“other option :%c\n”,ch); } printf(“optopt +%c\n”,optopt); }
执行 $./getopt –b option b:b $./getopt –c other option:c $./getopt –a other option :? $./getopt –a12345 option a:’12345’
在 20 世纪 90 年代(若是没有记错的话),UNIX 应用程序开始支持长选项,即一对短横线(而不是普通短 选项所使用的单个短横线)、一个描述性选项名称还能够包含一个使用等号链接到选项的参数。幸运的是,能够经过使用 getopt_long() 向程序添加长选项支持。您可能已经猜到了,getopt_long() 是同时支持长选项和短选项的getopt() 版本。getopt_long() 函数还接受其余参数,其中一个是指向 struct option 对象数组的指针。此结构至关直接,代码以下。
struct option { char *name; //name表示的是长参数名 int has_arg; //has_arg有3个值,no_argument(或者是0),表示该参数后面不跟参数值 // required_argument(或者是1),表示该参数后面必定要跟个参数值 // optional_argument(或者是2),表示该参数后面能够跟,也能够不跟参数值 int *flag; //用来决定,getopt_long()的返回值究竟是什么。若是flag是null,则函数会返回与该项option匹配的val值 int val; //和flag联合决定返回值 };
定义option的示例
struct option long_options[] = { {"a123", required_argument, 0, 'a'}, {"c123", no_argument, 0, 'c'}, }
函数定义以下
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);
#include #include int main( int argc, char **argv ) { struct option long_options[] = { {"a123", required_argument, 0, 'a'}, {"c123", no_argument, 0, 'c'}, } int opt; printf("starting... "); while((opt = getopt_long(argc, argv, "a:c", long_options, NULL)) != -1) { switch (opt) { case 'a': printf("It's a! "); printf("string of a:%s ",optarg); break; case 'c': printf("It's c! "); break; default: printf("You should look for help! "); exit(1); break; } } printf("end... "); return 0; } 编译后,假设生成a.out,能够试验一下。 ./a.out -a hello -c 输出: starting... It's a! string of a:hello It's c! end...
UNIX 用户始终依赖于命令行参数来修改程序的行为,特别是那些设计做为小工具集合 (UNIX 外壳环境)的一部分使用的实用工具更是如此。程序须要可以快速处理各个选项和参数,且要求不会浪费开发人员的太多时间。毕竟,几乎没有程序设计为仅处理命令行参数,开发人员更应该将精力放在程序所实际进行的工做上。getopt() 函数是一个标准库调用,可容许您使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项(带或不带附加的参数)。与其相似的 getopt_long() 容许在几乎不进行额外工做的状况下处理更具描述性的长选项,这很是受开发人员的欢迎。既然已经知道了如何方便地处理命令行选项,如今就能够集中精力改进您的程序的命令行,能够添加长选项支持,或添加以前因为不想向程序添加额外的命令行选项处理而搁置的任何其余选项。不要忘记在某处记录您全部的选项和参数,并提供某种类型的内置帮助函数来为健忘的用户提供帮助
http://www.cnitblog.com/zouzheng/archive/2007/04/02/25034.aspx
http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html