C++ linux命令解析参数 getopt_long 函数

Reference:

  1. getopt函数的使用
  2. 浅谈linux的命令行解析参数之getopt_long函数

在 LInux 中,经常需要各种命令,这些函数是如何解析的呢?一种方式是使用 GNU C 提供的函数 getoptgetopt_longgetopt_long_only 来解析命令行参数。

1. 关于命令行参数

命令行参数可以分为两类,一类是短选项,一类是长选项短选项在参数前加一杠“-”长选项在参数前连续加两杠“–”,如下表所示:其中 -a,-A,-b 都表示短选项,–all,–almost-all,–author 都表示长选项,他们两者后面都可选择性添加额外参数。如:–block-size=SIZE,其中 SIZE 便是额外参数。

在这里插入图片描述

2. getopt_long函数

getopt 函数只能处理短选项,而 getopt_long 函数两者都可以,可以说 getopt_long 函数包含了 getopt 的功能。因此,这里只介绍 getopt_long 函数。而 getopt_long 与 getopt_long_only 区别很小,等介绍完 getopt_long 后再提起会更好。

#include <unistd.h>  // getopt 函数所在头文件
extern char *optarg;  
extern int optind, opterr, optopt;  
#include <getopt.h>  // getopt_long 函数所在头文件
int getopt(int argc, char * const argv[],const char *optstring);  
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);

2.1 参数

  • 1.argcargv 和 main 函数的两个参数一致;
  • 2.optstring短选项字符串;
    形式如 a:b::cd,分别表示程序支持的命令行短选项有 -a、-b、-c、-d,冒号含义如下:
    (1) 只有一个字符,不带冒号-----只表示选项,如: -c
    (2) 一个字符,后面接一个冒号-----表示选项后面带一个参数,如: -a 100
    (3) 一个字符,后面接两个冒号-----表示选项后面带一个可选参数,即参数可有可无,如果带参数,则选项与参数之间不能有空格,如: -b200
  • 3.longopts:表示长选项结构体:
struct option
{
  const char *name;
  /* has_arg can't be an enum because some compilers complain about
     type mismatches in all the code that assumes it is an int.  */
  int has_arg;
  int *flag;
  int val;
};

static struct option long_options[] = {
    {"help", no_argument,       0,   'h'},
    {"cfg",  required_argument, 0,   'f'},
    {"http-proxy", required_argument, &lopt, 1 },
    {"http-user", required_argument, &lopt, 2 },
    {"http-passwd", required_argument, &lopt, 3 },
    {"http-proxy-user", required_argument, &lopt, 4 },
    {"http-proxy-passwd", required_argument, &lopt, 5 },
    {"http-auth-scheme", required_argument, &lopt, 6 },
    {nullptr, 0, nullptr, 0}
};

(1)name:表示选项的名称,如 help、cfg 等;

(2)has_arg:表示选项后面是否携带参数,该参数有三个不同值,如:
    no_argument(0): 参数后面不跟参数值,如:–help
    required_argument(1): 参数输入格式为:–参数 值 or –参数=值,如:./dist_measurment_node --cfg ./cal_result;
    optional_argument(2): 参数输入格式只能为:–参数=值

(3)flag:该参数有两种,空或者非空:
    如果参数为空(NULL)当选中某个长选项的时候,getopt_long 将返回 val 值,如: ./可执行程序 --help,getopt_long 的返回值为 h。
    如果参数不为空当选中某个长选项的时候,getopt_long 将返回 0,并且将 flag 指针指向 val 值,如:./可执行程序 --http-proxy=127.0.0.1:80,getopt_long 的返回值为 0,并且 lopt 值为 1。

(4)val:表示指定函数找到该选项时的返回值,或者当 flag 非空时指定 flag 指向的数据的值。

  • 4.longindex:longindex 非空,它指向的变量将记录当前找到参数符合 longopts 里的第几个元素的描述,即 longopts 的下标值。

2.2 全局变量

  • optarg:会被系统自动赋为当前选项的参数;
  • optind:表示下一个将被处理到的参数在 argv 中的下标值;
  • opterr:如果 opterr = 0,在getopt、getopt_long、getopt_long_only 遇到错误将不会输出错误信息到标准输出流。opterr 在非 0 时,向屏幕输出错误。
  • optopt:会被自动赋值当前未标识的选项;

2.3 返回值

  1. 如果短选项找到,那么将返回短选项对应的字符。

  2. 如果长选项找到,如果flag为NULL,返回val。如果flag不为空,返回0

  3. 如果遇到一个选项没有在短字符、长字符里面,或者在长字符里面存在二义性的,返回“?”

  4. 如果解析完所有字符没有找到(一般是输入命令参数格式错误,eg: 连斜杠都没有加的选项),返回“-1”

  5. 如果选项需要参数,忘了添加参数。返回值取决于optstring,如果其第一个字符是“:”,则返回“:”,否则返回“?”。

注意:

  1. longopts的最后一个元素必须是全0填充,否则会报段错误

  2. 短选项中每个选项都是唯一的。而长选项如果简写,也需要保持唯一性。

3. 示例

#include <getopt.h>

static struct option long_options[] = {
    {"help", no_argument,       0,   'h'},
    {"cfg",  required_argument, 0,   'f'},
    {nullptr, 0, nullptr, 0}
};

static void HelpInfo(char *argv[]) {
    printf("Usage: %s --cfg <cfgfile> or -f <cfgfile>\n", argv[0]);
}

int main(int argc, char *argv[])
{    
    int status = 0;
    int arg, index;
    std::string cfg_file;

    arg = getopt_long(argc, argv, "hf:", long_options, &index);
    if (arg == -1) { //见上文2.3.4:如果解析完所有字符没有找到,返回“-1”
        HelpInfo(argv); //传递入可执行文件名
        return -1;
    } else {
        switch (arg) {
        case 'h':
            HelpInfo(argv);
            return 0;
        case 'f':
            if (optarg) {
                cfg_file = optarg; //见上文2.2.1:会被系统自动赋为当前选项的参数,如:./可执行程序 -f Shuaiji,下面一句会打印:Use cfg: Shuaiji
                printf("Use cfg: %s\n", cfg_file.c_str()); 
            } else {
                HelpInfo(argv);
                return -1;
            }
        }
    }
	return status;
}
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泠山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值