简单、小巧、灵活的C++11单头文件的命令行参数解析库
2024-06-27
53
概述
命令行参数解析,在写一些命令行的程序时需要用到,args.hxx类似于Python的argparse,但在C++中,它具有静态类型检查,并且速度更快(也允许完全嵌套的组逻辑,而Python的argparse没有),支持自定义类型解析,子命令等。使用上,只需要在工程中include “args.hxx” 就可以正常使用,符合C++11规范,兼容性更好。
文档和源码
API文档地址: https://taywee.github.io/args
源码地址: at https://github.com/Taywee/args
范例
以下的所有代码示例都将是完整的代码示例,并带有一些输出。
简单范例
#include iostream
#include args.hxx
int main(int argc, char **argv)
{
args::ArgumentParser parser(This is a test program., This goes after the options.);
args::HelpFlag help(parser, help, Display this help menu, {h, help});
args::CompletionFlag completion(parser, {complete});
try
{
parser.ParseCLI(argc, argv);
}
catch (const args::Completion e)
{
std::cout e.what();
return 0;
}
catch (const args::Help)
{
std::cout parser;
return 0;
}
catch (const args::ParseError e)
{
std::cerr e.what() std::endl;
std::cerr parser;
return 1;
}
return 0;
}
运行输出:
% ./test
% ./test -h
./test {OPTIONS}
This is a test program.
OPTIONS:
-h, --help Display this help menu
This goes after the options.
%
布尔标志、特殊组类型、不同的匹配器构造
#include iostream
#include args.hxx
int main(int argc, char **argv)
{
args::ArgumentParser parser(This is a test program., This goes after the options.);
args::Group group(parser, This group is all exclusive:, args::Group::Validators::Xor);
args::Flag foo(group, foo, The foo flag, {f, foo});
args::Flag bar(group, bar, The bar flag, {b});
args::Flag baz(group, baz, The baz flag, {baz});
try
{
parser.ParseCLI(argc, argv);
}
catch (args::Help)
{
std::cout parser;
return 0;
}
catch (args::ParseError e)
{
std::cerr e.what() std::endl;
std::cerr parser;
return 1;
}
catch (args::ValidationError e)
{
std::cerr e.what() std::endl;
std::cerr parser;
return 1;
}
if (foo) { std::cout foo std::endl; }
if (bar) { std::cout bar std::endl; }
if (baz) { std::cout baz std::endl; }
return 0;
}
运行输出:
% ./test
Group validation failed somewhere!
./test {OPTIONS}
This is a test program.
OPTIONS:
This group is all exclusive:
-f, --foo The foo flag
-b The bar flag
--baz The baz flag
This goes after the options.
% ./test -f
foo
% ./test --foo
foo
% ./test --foo -f
foo
% ./test -b
bar
% ./test --baz
baz
% ./test --baz -f
Group validation failed somewhere!
./test {OPTIONS}
This is a test program.
...
% ./test --baz -fb
Group validation failed somewhere!
./test {OPTIONS}
...
%
参数标志、位置参数、列表
#include iostream
#include args.hxx
int main(int argc, char **argv)
{
args::ArgumentParser parser(This is a test program., This goes after the options.);
args::HelpFlag help(parser, help, Display this help menu, {h, help});
args::ValueFlagint integer(parser, integer, The integer flag, {i});
args::ValueFlagListchar characters(parser, characters, The character flag, {c});
args::Positionalstd::string foo(parser, foo, The foo position);
args::PositionalListdouble numbers(parser, numbers, The numbers position list);
try
{
parser.ParseCLI(argc, argv);
}
catch (args::Help)
{
std::cout parser;
return 0;
}
catch (args::ParseError e)
{
std::cerr e.what() std::endl;
std::cerr parser;
return 1;
}
catch (args::ValidationError e)
{
std::cerr e.what() std::endl;
std::cerr parser;
return 1;
}
if (integer) { std::cout i: args::get(integer) std::endl; }
if (characters) { for (const auto ch: args::get(characters)) { std::cout c: ch std::endl; } }
if (foo) { std::cout f: args::get(foo) std::endl; }
if (numbers) { for (const auto nm: args::get(numbers)) { std::cout n: nm std::endl; } }
return 0;
}
运行输出:
% ./test -h
./test {OPTIONS} [foo] [numbers...]
This is a test program.
OPTIONS:
-h, --help Display this help menu
-i integer The integer flag
-c characters The character flag
foo The foo position
numbers The numbers position list
-- can be used to terminate flag options and force all following
arguments to be treated as positional options
This goes after the options.
% ./test -i 5
i: 5
% ./test -i 5.2
Argument integer received invalid value type 5.2
./test {OPTIONS} [foo] [numbers...]
% ./test -c 1 -c 2 -c 3
c: 1
c: 2
c: 3
%
% ./test 1 2 3 4 5 6 7 8 9
f: 1
n: 2
n: 3
n: 4
n: 5
n: 6
n: 7
n: 8
n: 9
% ./test 1 2 3 4 5 6 7 8 9 a
Argument numbers received invalid value type a
./test {OPTIONS} [foo] [numbers...]
This is a test program.
...
命令行子命令
#include iostream
#include args.hxx
int main(int argc, char **argv)
{
args::ArgumentParser p(git-like parser);
args::Group commands(p, commands);
args::Command add(commands, add, add file contents to the index);
args::Command commit(commands, commit, record changes to the repository);
args::Group arguments(p, arguments, args::Group::Validators::DontCare, args::Options::Global);
args::ValueFlagstd::string gitdir(arguments, path, , {git-dir});
args::HelpFlag h(arguments, help, help, {h, help});
args::PositionalListstd::string pathsList(arguments, paths, files to commit);
try
{
p.ParseCLI(argc, argv);
if (add)
{
std::cout Add;
}
else
{
std::cout Commit;
}
for (auto path : pathsList)
{
std::cout path;
}
std::cout std::endl;
}
catch (args::Help)
{
std::cout p;
}
catch (args::Error e)
{
std::cerr e.what() std::endl p;
return 1;
}
return 0;
}
运行输出:
% ./test -h
./test COMMAND [paths...] {OPTIONS}
git-like parser
OPTIONS:
commands
add add file contents to the index
commit record changes to the repository
arguments
--git-dir=[path]
-h, --help help
paths... files
-- can be used to terminate flag options and force all following
arguments to be treated as positional options
% ./test add 1 2
Add 1 2
重构子命令
#include iostream
#include args.hxx
args::Group arguments(arguments);
args::ValueFlagstd::string gitdir(arguments, path, , {git-dir});
args::HelpFlag h(arguments, help, help, {h, help});
args::PositionalListstd::string pathsList(arguments, paths, files to commit);
void CommitCommand(args::Subparser parser)
{
args::ValueFlagstd::string message(parser, MESSAGE, commit message, {m});
parser.Parse();
std::cout Commit;
for (auto path : pathsList)
{
std::cout path;
}
std::cout std::endl;
if (message)
{
std::cout message: args::get(message) std::endl;
}
}
int main(int argc, const char **argv)
{
args::ArgumentParser p(git-like parser);
args::Group commands(p, commands);
args::Command add(commands, add, add file contents to the index, [](args::Subparser parser)
{
parser.Parse();
std::cout Add;
for (auto path : pathsList)
{
std::cout path;
}
std::cout std::endl;
});
args::Command commit(commands, commit, record changes to the repository, CommitCommand);
args::GlobalOptions globals(p, arguments);
try
{
p.ParseCLI(argc, argv);
}
catch (args::Help)
{
std::cout p;
}
catch (args::Error e)
{
std::cerr e.what() std::endl p;
return 1;
}
return 0;
}
运行结果:
% ./test -h
./test COMMAND [paths...] {OPTIONS}
git-like parser
OPTIONS:
commands
add add file contents to the index
commit record changes to the repository
arguments
--git-dir=[path]
-h, --help help
paths... files
-- can be used to terminate flag options and force all following
arguments to be treated as positional options
% ./test add 1 2
Add 1 2
% ./test commit -m my commit message 1 2
Commit 1 2
message: my commit message
自定义类型解析器
这里我们使用std::tuple
#include iostream
#include tuple
std::istream operator(std::istream is, std::tupleint, int ints)
{
is std::get0(ints);
is.get();
is std::get1(ints);
return is;
}
#include args.hxx
struct DoublesReader
{
void operator()(const std::string name, const std::string value, std::tupledouble, double destination)
{
size_t commapos = 0;
std::get0(destination) = std::stod(value, commapos);
std::get1(destination) = std::stod(std::string(value, commapos + 1));
}
};
int main(int argc, char **argv)
{
args::ArgumentParser parser(This is a test program.);
args::Positionalstd::tupleint, int ints(parser, INTS, This takes a pair of integers.);
args::Positionalstd::tupledouble, double, DoublesReader doubles(parser, DOUBLES, This takes a pair of doubles.);
try
{
parser.ParseCLI(argc, argv);
}
catch (args::Help)
{
std::cout parser;
return 0;
}
catch (args::ParseError e)
{
std::cerr e.what() std::endl;
std::cerr parser;
return 1;
}
if (ints)
{
std::cout ints found: std::get0(args::get(ints)) and std::get1(args::get(ints)) std::endl;
}
if (doubles)
{
std::cout doubles found: std::get0(args::get(doubles)) and std::get1(args::get(doubles)) std::endl;
}
return 0;
}
运行输出:
% ./test -h
Argument could not be matched: h
./test [INTS] [DOUBLES]
This is a test program.
OPTIONS:
INTS This takes a pair of integers.
DOUBLES This takes a pair of doubles.
% ./test 5
ints found: 5 and 0
% ./test 5,8
ints found: 5 and 8
% ./test 5,8 2.4,8
ints found: 5 and 8
doubles found: 2.4 and 8
% ./test 5,8 2.4,
terminate called after throwing an instance of std::invalid_argument
what(): stod
zsh: abort ./test 5,8 2.4,
% ./test 5,8 2.4
terminate called after throwing an instance of std::out_of_range
what(): basic_string::basic_string: __pos (which is 4) this-size() (which is 3)
zsh: abort ./test 5,8 2.4
% ./test 5,8 2.4-7
ints found: 5 and 8
doubles found: 2.4 and 7
% ./test 5,8 2.4,-7
ints found: 5 and 8
doubles found: 2.4 and -7
更多范例请参考github上的手册:https://github.com/Taywee/args
更新于:4个月前赞一波!3
相关文章
- 【说站】python模块如何传入参数
- 什么是...rest?收集剩余参数
- 【说站】Python命令行如何运行文件
- 【说站】Python有哪些命令行参数解析模块?
- PHP 命令行指令
- 生成带参数的二维码
- PHP7.4命令行报错:VC运行库和PHP版本不兼容
- TP6.0 命令行生成类库文件
- Nginx配置文件(nginx.conf)配置参数详解
- composer 全局参数
- Sublime Text 命令行工具 subl
- C#的控制台程序中如何设置命令行窗体的字体颜色,窗口宽度和高度,光标行数
- 在 Linux 命令行中重命名文件和目录
- 命令行输入python没有正确显示怎么办?
- 使用 Bootstrap 创建简单而灵活的面包屑导航
- Vue中的全局变量:在组件间共享数据的灵活解决方案
- Windows/Linux C语言如何实现可变参数的函数
- Windows中C语言网络编程时调用setsockopt设置组播参数报错10042(WSAENOPROTOOPT)
- Linux中命令行网络工具Netcat 介绍及使用
- script 标签 defer参数有什么用?
文章评论
评论问答