红联Linux门户
Linux帮助

Linux选项-getopt/getopt_long

发布时间:2014-12-14 09:28:20来源:linux网站作者:ytmayer

一、命令行简介

解释分析命令行通常是所以程序的第一个任务,C语言通过argc和argv参数来访问它的命令行参数。

最简单的命令行处理技术可以通过if判断来表示,如下例:

if(argc>1 && argv[1][0] =='-' && argv[1][1] =='h')  //判断命令行参数是否为-h  
{  
do _ some thing();  
}  

这样处理简单有序的命令行还可以,对于复杂的命令行处理显得有心无力,于是GNU提供两个函数专门用来处理命令行参数:

getopt 和getopt_long

 

二、getopt函数

getopt() 函数声明如下:

#include <unistd.h>
int getopt(int argc, char *const argv[], const char *optstring);

extern char *optarg;
 
extern int optind, opterr, optopt;

说明:

函数的argc和argv参数通常直接从main()的参数直接传递而来。optstring是选项字母组成的字串。如果该字串里的任一字符后面有冒号,那么这个选项就要求有选项参数。

当给定getopt()命令参数的数量 (argc)、指向这些参数的数组 (argv) 和选项字串 (optstring) 后,getopt() 将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有可识别的选项,将返回 -1,此任务就完成了。

getopt()所设置的全家变量包括:

optarg ---- 当前选项参数字符(如果有的话)

optind ---- argv的当前索引值。当getopt()在while循环中使用时,循环结束后,剩下的字串视为操作数,在
  argv[optind]至argv[argc-1]中可以找到。

optopt ---- 用于当发现无效选项字符的时候,getopt函数或者返回 "?" 或者返回 ":" 字符,并且optopt包含了
  所发现的无效选项字符,或者当输入非法参数的时候,由optopt带回输入的非法参数(字符)

opterr ---- 这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。

另外:

如果optstring参数的第一个字符是冒号,那么getopt会根据错误情况返回不同的字符:

(1):当错误是无效选项,getopt返回 "?"

(2):当错误是缺少选项参数,getopt返回 ":"

(3): 无错误发生时,正常返回的是对应的字符!

注:GNU getopt()第三个特点是optstring中的选项字符后面接两个冒号,就允许该选项有可选的选项参数。在选项参数不存在的情况下,GNU getopt()返回选项字符并将optarg设置为NULL。

例子:

#include<stdio.h>  
#include<unistd.h>  
#include<getopt.h>  
/*the variables bellow was define in getopt.h
extern char *optarg; 
extern int optind, opterr, optopt;
*/ 
char* para = ":ab:c"; 
void print_extern_val(void) 

   printf("optarg=%s.optind=%d.opterr=%d.optopt=%d=%c[END]/n", 
   optarg, optind, opterr, optopt, optopt); 

int main(int argc,char* argv[]) 

   int oc = -1; 

   char* b_input = NULL; 

   while((oc = getopt(argc,argv,para)) != -1)
   {
  switch(oc)  
  { 
  
  case 'a':
 printf("input para is a/n");
 print_extern_val(); 
 break; 
  
  case 'b':
 b_input = optarg;
 printf("input para is b,and optarg is %s/n",b_input);
 print_extern_val(); 
 break; 
  
  case 'c':  
 printf("input para is c/n");
 print_extern_val(); 
 break; 
  
  case ':':  
 printf("option %c requires an argument/n",optopt);
 print_extern_val();  
 break; 
  
  case '?':  
  default: 
 printf("option %c is invalid:ignored/n",optopt); 
 print_extern_val(); 
 break; 
  }
   } 

   return 0;
}  

结果:

[root@localhost opts]# ./getopt -a

input para is a

optarg=(null).optind=2.opterr=1.optopt=0=[END]

[root@localhost opts]# ./getopt -a -b

input para is a

optarg=(null).optind=2.opterr=1.optopt=0=[END]

option b requires an argument

optarg=(null).optind=3.opterr=1.optopt=98=b[END]

[root@localhost opts]# ./getopt -a -b mingming

input para is a

optarg=(null).optind=2.opterr=1.optopt=0=[END]

input para is b,and optarg is mingming

optarg=mingming.optind=4.opterr=1.optopt=0=[END]

[root@localhost opts]# ./getopt -a -d

input para is a

optarg=(null).optind=2.opterr=1.optopt=0=[END]

option d is invalid:ignored

optarg=(null).optind=3.opterr=1.optopt=100=d[END]

 

三、getopt_long函数

getopt_long () 用来处理长选项,使用 man 3 getopt_long ,得到其声明如下:

#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);  

前三个参数与getopt相同,下一个参数是指向数组的指针,这个数组是option结构数组,option结构称为长选项表,其声明如下:

struct  option 

{

const char *name;

int  has_arg;

int  *flag;

int  val;

 };  

 

结构中的元素解释如下:

const char *name :选项名,前面没有短横线

int  has_arg :描述长选项是否有参数,其值见下表
 

符号常量

数值

含义

no_argument

required_argument

optional_argument

0

1

2

选项没有参数

选项需要参数

选项参数是可选的

int  *flag :

如果该指针为NULL,那么getopt_long返回val字段的值;

如果该指针不为NULL,那么会使得它所指向的结构填入val字段的值,同时getopt_long返回0 (*flag = val, then return)

如果flag不是 NULL,但未发现长选项,那么它所指向的变量的数值不变。
 

返回值

含义

0

getopt_long() 设置一个标志,它的值与 option 结构中的 val 字段的值一样

1

每碰到一个命令行参数, optarg 都会记录它

'?'

无效选项

':'

缺少选项参数

'x'

选项字符 'x'

-1

选项解析结束

#include<stdio.h>  
#include<unistd.h>  
#include<getopt.h>  
/*the variables bellow was define in getopt.h
extern char *optarg; 
extern int optind,  opterr,  optopt;
*/ 
char* para = ":am:cf:v"; 
int do_all = 0; 
int do_help = 0; 
int do_version = 0; 
char* file = NULL; 
void print_extern_val(void) 

printf("optarg=%s.optind=%d.opterr=%d.optopt=%d=%c[END]/n",  
optarg, optind, opterr, optopt, optopt); 

/*
struct option 
{
   const char *name;
   int has_arg;
   int *flag;
   int val;
};
*/ 
struct option longopt[]= 

   {"all", no_argument, &do_all, 1},  

   {"file", required_argument, NULL, 'f'},   // val='f'---> para中对应的选项  返回 'f'  

   {"help", no_argument, &do_help, 1}, //返回 0 并置do_help = 1(1为对应的val)  

   {"version", no_argument, &do_version, 1},  

   {"ming", required_argument, NULL, 'm'},  

   {0, 0, 0, 0},   //end flag  

}; 
int main(int argc, char* argv[]) 

   int oc = -1; 

   char* m_input = NULL; 

   while((oc = getopt_long(argc, argv, para, longopt, NULL)) != -1)
   { 
  printf("getopt_long()return %d(%c)./n", oc, oc); 
  switch(oc)  
  { 
  
  case 'a':  
 printf("input para is a/n"); 
 print_extern_val(); 
 break; 
  
  case 'm': 
 m_input = optarg;
 printf("input para is m,and optarg is %s/n",m_input);
 print_extern_val(); 
 break; 
  
  case 'c':  
 printf("input para is c/n"); 
 print_extern_val(); 
 break; 
  
  case 'v':  
 printf("input para is v/n"); 
 print_extern_val(); 
 break; 
  
  case 'f':  
 printf("input para is f/n");
 file = "helloworld"; 
 print_extern_val(); 
 break; 
  
  case 0: 
 printf("0-0-0-0-0-0-0-0/n");
 print_extern_val(); 
 break; 
  
  case ':':  
 printf("option %c requires an argument/n", optopt); 
 print_extern_val(); 
 break; 
  
  case '?':  
  default:
 printf("option %d is invalid:ignored/n", optopt); 
 print_extern_val(); 
 break; 
  } 

   } 

   printf("do_all=%d/n", do_all);
   printf("do_help=%d/n", do_help); 
   printf("do_version=%d/n", do_version); 
   printf("do_file=%s/n", file); 
   printf("m_input=%s/n", m_input); 

   return 0; 

}  

结果:

[root@localhost opts]# ./getopt_long --ming mayer

getopt_long()return 109(m).

input para is m,and optarg is mayer

optarg=mayer.optind=3.opterr=1.optopt=0=[END]

do_all=0

do_help=0

do_version=0

do_file=(null)

m_input=mayer

[root@localhost opts]# ./getopt_long -m mayer  

getopt_long()return 109(m).

input para is m,and optarg is mayer

optarg=mayer.optind=3.opterr=1.optopt=0=[END]

do_all=0

do_help=0

do_version=0

do_file=(null)

m_input=mayer

[root@localhost opts]# ./getopt_long -k

getopt_long()return 63(?).

option 107 is invalid:ignored

optarg=(null).optind=2.opterr=1.optopt=107=k[END]

do_all=0

do_help=0

do_version=0

do_file=(null)

m_input=(null)

[root@localhost opts]# ./getopt_long --mayer

getopt_long()return 63(?).

option 0 is invalid:ignored

optarg=(null).optind=2.opterr=1.optopt=0=[END]

do_all=0

do_help=0

do_version=0

do_file=(null)

m_input=(null)

[root@localhost opts]# ./getopt_long --ming

getopt_long()return 58(:).

option m requires an argument

optarg=(null).optind=2.opterr=1.optopt=109=m[END]

do_all=0

do_help=0

do_version=0

do_file=(null)

m_input=(null)

[root@localhost opts]# ./getopt_long --all

getopt_long()return 0().

0-0-0-0-0-0-0-0

optarg=(null).optind=2.opterr=1.optopt=0=[END]

do_all=1

do_help=0

do_version=0

do_file=(null)

m_input=(null)