【转】getopt分析命令行参数

(一)

在Linux中,用命令行执行可执行文件时可能会涉及到给其加入不同的参数的问题,例如:

./a.out -a1234 -b432 -c -d

程序会根据读取的参数执行相应的操作,在C语言中,这个功能一般是靠getopt()这个函数,结合switch语句来完成的,首先来看下面的代码:

#include <stdio.h>
#include <unistd.h>

int main(int argc,char *argv[])
{
  int ch;
  opterr=0;
  
  while((ch=getopt(argc,argv,"a:b::cde"))!=-1)
  {
    printf("optind:%d\n",optind);
    printf("optarg:%s\n",optarg);
    printf("ch:%c\n",ch);
    switch(ch)
    {
      case ‘a‘:
        printf("option a:‘%s‘\n",optarg);
        break;
      case ‘b‘:
        printf("option b:‘%s‘\n",optarg);
        break;
      case ‘c‘:
        printf("option c\n");
        break;
      case ‘d‘:
        printf("option d\n");
        break;
      case ‘e‘:
        printf("option e\n");
        break;
      default:
        printf("other option:%c\n",ch);
    }
    printf("optopt+%c\n",optopt);
  }

}

用gcc编译后,在终端行执行以上的命令:

./a.out -a1234 -b432 -c -d

则会有如下的输出:

optind:2
optarg:1234
ch:a
option a:‘1234‘
optopt+
optind:3
optarg:432
ch:b
option b:‘432‘
optopt+
optind:4
optarg:(null)
ch:c
option c
optopt+
optind:5
optarg:(null)
ch:d
option d
optopt+

要理解getopt()函数的作用,首先要清楚带参数的main()函数的使用:
main(int argc,char *argv[])中的argc是一个整型,argv是一个指针数组,argc记录argv的大小。上面的例子中。
argc=5;
argv[0]=./a.out
argv[1]=-a1234
argv[2]=-b432
argv[3]=-c
argv[4]=-d
getopt()函数的原型为getopt(int argc,char *const argv[],const char *optstring)。
其中argc和argv一般就将main函数的那两个参数原样传入。
optstring是一段自己规定的选项串,例如本例中的"a:b::cde",表示可以有,-a,-b,-c,-d,-e这几个参数。
“:”表示必须该选项带有额外的参数,全域变量optarg会指向此额外参数,“::”标识该额外的参数可选(有些Uinx可能不支持“::”)。
全域变量optind指示下一个要读取的参数在argv中的位置。
如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符。
如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。

(二)

#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储存第一个不包含选项的命令行参数。

首先说一下什么是选项,什么是参数。

字符串optstring可以下列元素,
1.单个字符,表示选项,
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。
3 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。

getopt处理以‘-’开头的命令行参数,如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。

#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()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,如果不希望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’

getopt 函数
函数定义:
#include 
int getopt(int argc, char * const argv[], 
        const char *optstring);

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

#define _GNU_SOURCE
#include

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()函数是用来解析命令行参数的。这里,主要解释getopt_long()。

getopt_long()的头两参数,argc和argv分别是传递给main()的参数的个数和参数数组(和main()的argc和argv是一个概念)。

getopt_long()中,optstring是一个字符串,表示可以接受的参数。例如,"a:b:cd",表示可以接受的参数是a,b,c,d,其中,a和b参数后面

跟有更多的参数值。(例如:-a host --b name)

getopt_long()中,参数longopts,其实是一个结构的实例:
struct option {
  const 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联合决定返回值
}

给个例子:

struct option long_options[] = {
  {"a123",       required_argument,      0, ‘a‘},
  {"c123",       no_argument,            0, ‘c‘},
}

现在,如果命令行的参数是-a 123,那么调用getopt_long()将返回字符‘a‘,并且将字符串123由optarg返回(注意注意!字符串123由optarg带

回!optarg不需要定义,在getopt.h中已经有定义)
那么,如果命令行参数是-c,那么调用getopt_long()将返回字符‘c‘,而此时,optarg是null。

最后,当getopt_long()将命令行所有参数全部解析完成后,返回-1。

看来,我说的有点混乱,那么,看个例子,我相信,代码最能说明问题:

#include 
#include 
#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...

时间: 2024-10-12 17:34:37

【转】getopt分析命令行参数的相关文章

getopt 分析命令行参数 -n -t 1

在Linux中,我们常常用到 ls -l 等等之类带有选项项的命令,下面,让我们用C++来实现该类似的命令. 在实现之前,首先,我们来介绍一下一个重要函数:getopt() 表头文件 #include<unistd.h> 定义函数 int getopt(int argc,char * const argv[ ],const char * optstring); 函数说明: 用来分析命令行参数.参数 argc 和 argv 是由 main() 传递的参数个数和内容. 参数 optstring为选

getopt函数(分析命令行参数)

相关函数表头文件 #include<unistd.h>定义函数 int getopt(int argc,char * const argv[ ],const char * optstring);函数说明 getopt()用来分析命令行参数.参数argc和argv是由main()传递的参数个数和内容.参数optstring 则代表欲处理的选项字符串.此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母.如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参

getopt(分析命令行参数)

ref:http://vopit.blog.51cto.com/2400931/440453 相关函数表头文件 #include<unistd.h>定义函数 int getopt(int argc,char * const argv[ ],const char * optstring);函数说明 getopt()用来分析命令行参数.参数argc和argv是由main()传递的参数个数和内容.参数optstring 则代表欲处理的选项字符串.此函数会返回在argv 中下一个的选项字母,此字母会对

getopt函数的使用——分析命令行参数

getopt(分析命令行参数) getopt(分析命令行参数) 短参数的定义 返回值 范例 getopt_long 相关函数表头文件 #include<unistd.h> 定义函数 int getopt(int argc,char * const argv[ ],const char * optstring); 函数说明 getopt()用来分析命令行参数.参数argc和argv是由main()传递的参数个数和内容.参数optstring 则代表欲处理的选项字符串.此函数会返回在argv中下一

boost 分析命令行参数

[cpp] view plaincopy #include <boost/program_options.hpp> #include <iostream> #include <vector> using namespace std; using namespace  boost::program_options; int main(int argc, char* argv[]) { string one ; // 外部变量 存储 参数one的值 vector<st

Python3+getopt解析命令行参数

一.说明 在学C语言的时候就知道可以通过argc获取命令行参数个数,可以通过argv获取具体参数.但自己写的程序获取到的参数一是没有键值形式二是写的参数不能乱序,和系统命令不太一样. 再往后点知道有getopt这个东西,但印象中尝试理解其用法很多次都没什么结果:最近又越来多写程序,再次感觉很有必要掌握. 这里以Python3为例演示getopt,python感觉就是C的封装,C的getopt应该也类似. 二.程序代码 此程序中设置-h/-n/-p三个选项,-h不带值-n和-p带值:三个参数设置等

Python 命令行参数和getopt模块详解

1.需求来源 有时候我们需要写一些脚本处理一些任务,可能根据不同的条件输入不同的命令,来完成不同的任务.能不能做到跟linux操作系统一样,看着更高大上一点呢? 答案当然是可以的啦!getopt能满足你的需求 先看个linux 中的系统命令吧:最终目的就是写出类似的脚本. 2.getopt介绍 getopt这个函数 就是用来抽取 sys.argv 获得的用户输入来确定执行步骤. getopt是个模块,而这个模块里面又有getopt 函数,所以getopt需要这样这样用. getopt.getop

MFC解析启动命令行参数——CCommandLineInfo类

MFC中CCommandLineInfo类被用于分析启动应用时的命令行参数. MFC应用一般都会在它的应用对象中使用函数InitInstance()创建这个类的一个本地实例.然后把该对象传给CWinApp::ParseCommandLine(),ParseCommandLine()又重复调用ParseParam()填充CCommandLineInfo对象.最后,CCommandLineInfo对象被传给CWinApp::ProcessShellCommand()来处理命令行参数和选项.所以我们会

【Python 命令行参数解析: optparse 模块】

大家在使用Python进行脚本开发时,经常需要通过终端交互的方式对Python的脚本模块进行调用.这时在 Python模块中提供基础的命令行参数支持是必不可少的.那么,在Python中我们如何实现命令行参数的传入和解析呢,如下内容将对此进行简要的介绍. Python对命令行参数解析的支持 Python中通过两个内建模块对命令行参数解析进行支持:getopt 和 optparse 两种内置支持 模块名 功能说明 getopt 对命令行参数进行简单的处理 optparse 能够对命令行参数进行复杂的