cxxopts–readme分析文档

cxxopts是一个轻量级命令行文本分析项目,我门可以自定义选项来解析命令行中输入的字符,达到一定的目的,转化为我们想让计算机得到的结果

[github地址](arqqqq/cxxopts: Lightweight C++ command line option parser (github.com))

1.快速开始

cxxopt支持传统的gun标准语法,任何如下的选项定义是被允许的

--long
--long = argument
--long argument
-a
-ab
-abc

任何的**--**标识后面附带的字符都会被解析为位置参数

2.基础

你需要包含cxxxopts头文件并创建选项options才能使用cxxopts

#include<cxxopts.hpp>

创建一个解析选项实例

//cxxopts::Options option("名称","描述");
cxxopts::Options option("MyProgram","this is My Program");

1.可以用Options添加一些解析选项

options.add_options()("d,debug", "Enable debugging") // a bool parameter("i,integer", "Int param", cxxopts::value<int>())("f,file", "File name", cxxopts::value<std::string>())("v,verbose", "Verbose output", cxxopts::value<bool>()->default_value("false"));

方法add_options返回一个OptionAdder类的引用,OptionAdder重载了()运算符,在cxxopts中的源码为

std::basic_regex<char> option_specifier("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?");inline
OptionAdder&
OptionAdder::operator()
(const std::string& opts,const std::string& desc,const std::shared_ptr<const Value>& value,std::string arg_help
)
{std::match_results<const char*> result;std::regex_match(opts.c_str(), result, option_specifier); //通过正则表达式来匹配参数opts中的目标字串if (result.empty()){throw_or_mimic<invalid_option_format_error>(opts); //如果解析出来的结果是无效的,会抛出异常}const auto& short_match = result[2]; //子式1const auto& long_match = result[3]; //子式2if (!short_match.length() && !long_match.length()) //如果长短选项都没有的话,会抛出异常{throw_or_mimic<invalid_option_format_error>(opts);} else if (long_match.length() == 1 && short_match.length()) //长选项的字符数量不能够为1{throw_or_mimic<invalid_option_format_error>(opts);}auto option_names = [] //一个lambda表达式,(const std::sub_match<const char*>& short_,const std::sub_match<const char*>& long_){if (long_.length() == 1){return std::make_tuple(long_.str(), short_.str());}return std::make_tuple(short_.str(), long_.str()); //返回一个通过make_tuple自动推断构造器类型,返回一个OptionAdder}(short_match, long_match);m_options.add_option (m_group,std::get<0>(option_names),std::get<1>(option_names),desc,value,std::move(arg_help));return *this;
}

在类OptionAdder中,有两个成员变量,一个Option对象my_options,表示当前是在那个选项组别下,另外一个是一个string对象my_group,表示我的选项组别,重载的OptionAdder一共有四个参数,有两个参数具有默认值,分别是

  • opts——解析选项,可以是长选项,也可以是短选项,也可以是两者的组合
  • desc——选项的描述,用于在帮助文档中的选项功能的描述,不具默认值,必须传入
  • cxxopts::value<>()——一个cxxopts头文件中定义的泛型类,默认值为cxxopts(),代表着与声明值对应的value
  • arg_help——具体还不清楚有什么功效,默认值为**""**

Options are declared with a long and an optional short option. A description must be provided. The third argument is the value, if omitted(默认值) it is boolean. Any type can be given as long as it can be parsed, with operator>>.(任何类型都可以给出,只要他可以被解析,使用操作符<<)

2.通过prase来解析命令行

可以通过prase来解析命令行中输入的选项

auto result = options.prase(argc,argv);

options.prase返回一个PraseResult类,这个类也是在cxxopts中定义的,存放着解析结果

3.通过as来获取value

可以通过results[“之前添加的选项”]来获取value值

auto res = result["opt"].as<type>();

opt必须是之前通过add_options添加的选项,否则会抛出异常,并且使用的选项一定是要在作用域内声明的

3.未被确认的参数

可以通过参数设置方法**allow_unrecognised_options()**来跳过没有被定义的选项

options.allow_unrgcognised_options();

通过这个方法来跳过那些没有在options中定义的选项里面,并且可以通过**results.unmatched()**来取得这些跳过的字符串,比如可以看到代码

#include "cxxopts.hpp"
#include <iostream>
void prase(int argc,const char* argv[]){try{cxxopts::Options options("MyTest","a test program"); //搭建Option类options.positional_help("[Positional help]").show_positional_help();options.set_width(70).allow_unrecognised_options().add_options("myopt")("i,int","a integer",cxxopts::value<int>())("f,float","a float",cxxopts::value<float>())("vector","a list of double",cxxopts::value<std::vector<double>>());auto result = options.parse(argc,argv);if(result.count("int")){std::cout<<"int ="<<result["int"].as<int>()<<std::endl;}if(result.count("float")){std::cout<<"float ="<<result["float"].as<float>()<<std::endl;}if(result.count("vector")){std::cout<<"vector = ";const auto res = result["vector"].as<std::vector<double>>();for(const auto v:res){std::cout<<v<<" , ";}std::cout<<std::endl;}const auto res = result.unmatched(); //收取那些没有被定义的字符串std::cout<<"unmatched opt: ";for(auto vs:res){std::cout<<vs<<" , ";}std::cout<<std::endl;std::cout<<"Saw "<<result.arguments().size()<<" arguments"<<std::endl;}catch (cxxopts::OptionException &e){std::cout<<"parse error "<<e.what()<<std::endl;}
}int main(){int argc = 10;const char* argv[] = {"a","-i","100","vv","cc","hello","--float","1000","--vector=1.0,11.0,112.2","hhh"};prase(argc,argv);return 0;
}
//在运行结果中会有一个
//unmatched opt: vv,cc,hello,hhh, 这些都是没有被定义的选项

可以通过unmatched方法来获取那些被跳过的字符串,注意这里是字符串,这也就意味着只能够存入不带-的字符,如果一个命令行字符是形如-abc的形式,他会被认定为一个字符而不会被存入到unmatched方法获得的这个vector里面

4.异常

cxxopts中的异常分为两个方面,一个是定义选项的错误,另一个是解析参数列表的错误,这些异常都定义在cxxopts的OptionException里面,定义选项的错误为派生出来的optionspecException,解析参数的异常OptionParseException,所有异常都可以通过what()函数来解释异常信息

5.帮助文档

在cxxopts中,如果定义了选项,可以通过调用**help()**方法来获取这些选项的帮助文档,可以看下面的代码


#include<iostream>
#include "cxxopts.hpp"using namespace std;void help(){try{cxxopts::Options options("MyOpt","this is a opt group");options.positional_help("help");options.show_positional_help();options.set_width(70).allow_unrecognised_options().add_options("mygroup")("i,int","a integer",cxxopts::value<int>())("f,float","a float",cxxopts::value<float>())("v,vector","a list of int",cxxopts::value<std::vector<int>>());cout<<options.help(); //关键就在于这个help方法,能将添加的选项整理出来供使用者参考}catch (cxxopts::OptionException &e){cout<<e.what()<<endl;exit(1);}
}int main(){help();return 0;
}

/home/zrshonor/CLionProjects/cxxopts/cmake-build-debug/src/example
this is a opt group—>之前的options类的描述
Usage:
MyOpt [OPTION…]

mygroup options:—>选项组别,小分组,可以有很多个小分组
-i, --int arg a integer //从左到右依次为,短选项,长选项,选项描述
-f, --float arg a float
-v, --vector arg a list of int

Process finished with exit code 0

至于这个help输出的帮助文档,会看到在选项后面会有一个arg,这是OptionAdder类的最后一个参数,默认为arg(argument),也可以自定义

6.位置参数

位置参数可以被选择性地解析一个或者多个选项

options.parse_positional({"first", "second", "last"})

"last"应该是一个容器类型的选项的名称,而其他的应该只有一个值,大致想表达的意思是,你可以用三个位置参数来获取到在这个const char* argv[]字符数组中没有被匹配到的数据,相当于去首先很明显通过函数传入的option必须是在之前定义了的,对项目中的example.cpp的代码进行测试发现,在parse方法定义中有这么一句

options.parse_positional({"input", "output", "positional"});

通过使用不同的参数传入得到的解析方法,可以分析得到

  • input是option里面定义的一个选项,如果没有在数组里面没有匹配到--input,那么第一个不符合选项的第一个字符将是input的值
  • output也是同样的道理
  • positional这个位置参数对应的value是一个容其类型,他相当于一个位置参数,其对应的value值不仅可以收纳匹配到的选项值,而且可以收纳那些没有被匹配到的剩余字符,当此时,你再去调用**unmatched()**方法来获取到没有匹配到的字符是一个无效的操作

总结的来说的话,调用parse_positional方法后,传入的那些选项参数会首先在数组中查找匹配的的选项,如果有匹配的选项,那么就跟正常匹配没有什么区别,否则他会按照顺序,以分配的方式将选项分配到位

可以看测试例子,代码是cxxopts项目中自带的example.cpp,下面是main函数的测试用例

int argc = 7;const char* argv[] = {"a","--input","inp","--output=b.bin","t1","t2","t3"};parse(argc,argv);

结果为
Input = inp
Output = b.bin
Positional = {t1, t2, t3, }

Arguments remain = 7
Saw 5 arguments

可以看到input选项匹配到了一个结果,output同样的也匹配到了一个结果,但是positional选项没有与之匹配到的选项,所以说就按照顺序,将后面的没有匹配到的字符分配给它,那么这样的话,可以对代码进行一定的更改,将符合前两个的选项撤销掉,可以看到

int argc = 4;const char* argv[] = {"a","t1","t2","t3"};parse(argc, argv);

Input = t1
Output = t2
Positional = {t3, }

Arguments remain = 4
Saw 3 arguments

因为都没有匹配项,那么就是按照顺序分配,第一个给input,第二个给output,最后的都给positional,

需要注意的是,传入的字符数组中的第一个元素是会被忽略掉的

7.默认值和隐式值

对于某些选项,我们可以为其设置默认值,假如有下面的一个实例

cxxopts::Option options("mytest","a test example");
options.positional_help("[optional args]");
options.show_positional_help();options.set_width(70).set_tab_expansion().allow_unrecognised_options().add_options("my_opt")("f,float","a float number",cxxopts::value<float>())("i,int","a integer",cxxopts::value<int>()->default_value("0"));

可以看到,在上面的代码中,设置了两个选项,一个具备默认值,另一个不具备,这样就在解析命令行参数时也会存在着部分差异

int argc = 10;const char* argv[] = {"a","--float","--int"};

可以看到上面的示例代码中,–float这样的声明解析会报错,因为float不具备默认值,一旦解析到声明语句,那么就必将会对这个语句进行初始化,程序在后面搜索与之匹配的初始化值,如果搜索不到,对于设置了默认值的选项就会以默认值代替,没有设置默认值的话就会抛出异常,所以需要这样地修改

int argc = 10;const char* argv[] = {"a","--float=100","--int"};

隐式值也是如此,在两个选项被同时定义的时候,如果没有对其赋值,选项值会用隐式值代替

cxxopts::value<type>()->implicit_value("隐式值")

这样就说明了--opt这样的选项被解析出来设置了隐式值的会用隐式值代替,没有隐式值的话看有没有设置默认值,有的话用默认值代替,没有的话抛出异常,--opt=value这样的声明就会用value来给声明值赋值

8.布尔值

布尔选项有一个默认的隐式值"true",他可以被重写,其效果是,假如"-o"的value为布尔类型,因为没有初始值,会被置为true,当然也可以用-o=value来赋值,并且也可以自己设置默认值和隐式值

9.列表声明

可以采用这样的定义方式来获取一个列表声明,比如cxxopts::value<std::vector<type>>()来匹配一个列表,比如对于下面的代码

"--list = 1,1.0,1.2,1.3" //用一个value值为std::vector<double>的选项list来匹配

可以匹配一个列表,通过定义value值为vector的选项,列表的不同元素之间用,隔开,他是定义在cxxopts中的一个宏CXXOPTS_VECTOR_DELIMITER

10.相同的选项可以定义不同的数值

相同的声明可以赋予不同的寓意,这样的选项设置可以通过列表来实现,比如

--use train --use plane

可以将其value设置为vector

github开源项目cxxopts一个轻量级c++命令行解析器分析文档(基于README)相关推荐

  1. Linux命令行如何编辑word文档,在Linux平台下用命令行工具显示Word文档

    在Linux平台下用命令行工具显示Word文档 ·Antiword ·Catdoc ·wvWare[@more@] Viewing Word files at the command line Wed ...

  2. Node交互式命令行工具开发——自动化文档工具

    转载自:小磊 https://segmentfault.com/a/1190000039749423 nodejs开发命令行工具,流程相对简单,但一套完整的命令行程序开发流程下来,还是需要下点功夫,网 ...

  3. .NET:命令行解析器介绍

    背景 经常需要开发一下小工具,之前都是自己解析命令行参数,接触过动态语言社区以后,发现命令行解析有特定的模式和框架可以利用,本文介绍一个 .NET 平台的类库. 示例 需求 拷贝文件,如:CopyFi ...

  4. [Python] argparse命令行解析器的使用

    参考了python文档argparse- 用于命令行选项,参数和子命令的解析器和一篇非常非常优秀的博客python命令行解析模块argpars. 该argparse模块可以轻松编写用户友好的命令行界面 ...

  5. 一个不错的命令行解析类

    原文链接:Command line parser 作者所考虑的语法是: CommandLine::=[<Key> [,<Key>]] <Key>::=<Del ...

  6. 基于cobra的go语言命令行解析器

    ubuntu安装cobra $ sudo apt install cobra Reading package lists... Done Building dependency tree Readin ...

  7. Python 命令行解析器argparse及传参数详解

    源码实例一 from argparse import ArgumentParserparser = ArgumentParser(description='Beeswarm')group = pars ...

  8. 怎么退出python命令行cd找到txt文档_《python怎么读取txt文件》

    python怎么创建一个txt文件 python怎么创建txt文件的方法. 如下参考: 1.首用内置的空闲编辑器编辑(单击并选择copy),如下图所示. 2.您可以下载记事本和其他编辑软件,以支持多种 ...

  9. Linux重签名工具程序及命令行重签ipa文档

    au-signer推出了Linux系统命令行重签名ipa的程序 适用于自动化签名的实现 au-signer工具官网 http://sign.applicationloader.net/ 命令行签名包括 ...

  10. raspberryPi摄像头命令行软件raspistill帮助文档

    目录 作用 使用格式 常用命令: 图像参数与命令 预览参数与命令 图像参数与命令2 提示 原博文:https://www.cnblogs.com/jikexianfeng/p/7130843.html ...

最新文章

  1. Linux SWAP分区占用率高,刷新SWAP分区方法
  2. mysqldump命令详解(转载)
  3. android6.0进入Material Design时代
  4. Windows与Linux拷贝数据
  5. 模式识别,计算机视觉,计算机图形学,智能控制,信号处理,语音识别,知识处理,机器学习,数据挖掘领域区别
  6. 早该改了,只是我们太穷了
  7. hudo as3 网络通信框架
  8. jQuery对象与dom对象的转换
  9. python数据科学手册pdf中文版百度云,Python数据科学手册 英文pdf源码
  10. 国内外贵金属白银有何区别?
  11. fusion 360动态观察的快捷键
  12. java int 运算符,java中各种运算符
  13. CTFshow 2022 菜狗杯部分WEB WP
  14. Swiper实现手风琴式的图片展示
  15. Verilog-always语句
  16. STM32解析航模遥控器的PPM信号
  17. 睡眠质量不好怎么改善,这些助眠好物让你失眠快速入睡
  18. 8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号下...
  19. 【医学信息学】研究和统计——队列研究和数据分析
  20. 美国挤压阿里不是好兆头

热门文章

  1. 分享:蛋花儿主题WordPress瀑布流 V1.05(收费版)
  2. 架构师之殇:一个反对“平台团队”的案例
  3. 论AI在叮咚智能音箱中的演进和应用
  4. 微信引流技巧,精准日加100+粉丝
  5. kindle paperwhite 完美越狱,KPV / Koreader 安装
  6. 【sv】局部数据存储: 自动存储vs静态存储
  7. 疯狂打CALL,机器人抢镜时尚大典
  8. 如何查看当前域名的注册信息?
  9. 阿里云DNS专家,手把手教你定位域名解析不生效
  10. Color Models (RGB, CMY, HSI)