uck*_*man 16 c++ boost-program-options
指示命令行程序选项结束的传统方法是使用该选项--.如何让boost :: program_options将此识别为一个选项并接受命令行的其余部分作为位置参数?以下不起作用:
namespace po = boost::program_options;
po::positional_options_description posOpts;
posOpts.add("keywords", 1);
posOpts.add("input", 1);
std::vector<std::string> final_args;
po::options_description desc("Allowed Options");
desc.add_options()
...
("", po::value< std::vector<std::string> >(&final_args)->multitoken(), "end of options")
...
;
po::command_line_parser(argc, argv).options(desc).positional(posOpts).run();
Run Code Online (Sandbox Code Playgroud)
如果我foo bar作为参数给出,我什么都没有final_args(正如预期的那样),但是当我-- foo bar作为参数给出时(我期望找到final_args[0] == "foo"和final_args[1] == "bar").我在这里假设这--是一个长参数,空字符串作为其参数名称.相反,如果它应该被解释为一个短参数,-作为参数名称,我该如何指定?从我可以看到,将参数规范从""to 更改为",-"不影响结果.
如何让boost :: program_options --正确处理?
编辑:这是尝试通过创建一个Tim Sylvester建议extra_style_parser:
std::vector<po::option> end_of_opts_parser(std::vector<std::string>& args) {
std::vector<po::option> result;
std::vector<std::string>::const_iterator i(args.begin());
if (i != args.end() && *i == "--") {
for (++i; i != args.end(); ++i) {
po::option opt;
opt.string_key = "pargs";
opt.original_tokens.push_back(*i);
result.push_back(opt);
}
args.clear();
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
"pargs" 被添加到这样的选项:
("pargs", po::value< std::vector<std::string> >(&pargs), "positional arguments")
Run Code Online (Sandbox Code Playgroud)
--在参数列表中使用a运行此操作会导致required_option异常.(我得到类似的结果,如果不是po::option为每个尾随arg 制作一个,我将它们全部打包成po::option::original_tokens一个po::option.)
我有点困惑,因为boost::program_options已经完成了这一切:
$ ./testprog --the-only-option=23 aa --unknown bb
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::program_options::unknown_option> >'
what(): unknown option unknown
Aborted
$ ./testprog --the-only-option=23 -- aa --unknown bb
the only option: 23
positional: aa
positional: --unknown
positional: bb
Run Code Online (Sandbox Code Playgroud)
该程序:
#include <boost/program_options.hpp>
#include <iostream>
#include <vector>
using namespace std;
namespace po = boost::program_options;
static bool handle_command_line(int argc, char *argv[])
{
po::options_description desc("Allowed options");
desc.add_options()
("help", "Describe command line options")
("the-only-option", po::value<string>(), "some option")
;
po::options_description hidden;
hidden.add_options()
("positional", po::value<vector<string> >())
;
po::options_description all_options;
all_options.add(desc).add(hidden);
po::positional_options_description p;
p.add("positional", -1);
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).
options(all_options).positional(p).run(), vm);
po::notify(vm);
if (vm.count("help")) {
cout << "Usage: " << argv[0] << " [options] [args]" << endl;
cout << desc << "\n";
return false;
}
if (vm.count("the-only-option"))
cout << "the only option: " << vm["the-only-option"].as<string>() << endl;
if (vm.count("positional")) {
const vector<string> &v = vm["positional"].as<vector<string> >();
vector<string>::const_iterator it = v.begin();
for (; it != v.end(); ++it)
cout << "positional: " << *it << endl;
}
return true;
}
int main(int argc, char *argv[])
{
if (!handle_command_line(argc, argv))
return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有一个简单的,不令人满意的解决办法:移交前argv到command_line_parser,检查是否--发生了.如果是这样,请重置argc为--隐藏它的位置以及跟踪它的参数command_line_parser.然后,在完成解析后--,手动处理位置参数.布莱什!
我也有同样的疑问,但放弃了。
我相信执行此操作的方法是调用program_options::command_line_parser::extra_style_parser(),向其传递一个函数,该函数通过引用获取字符串向量并返回 s 向量option(请参阅cmdline.hppstyle_parser中的 typedef )。
您的函数需要检测第一个标记是“--”,创建一个新option对象,将输入中的所有其余标记放入 的option值向量中,并清空输入向量。请参阅program_options::detail::cmdline::parse_long_option等,了解libs/program_options/src/cmdline.cpp一些开始的内容。
您可能需要注册一个特定的选项值来使用,以便您可以option在解析结束时轻松找到这个特殊对象,并从中提取一组附加的非选项参数。
我希望能给你一些代码,但我从来没有时间真正这样做,我最终只是在标准输入上每行获取一个附加参数。
编辑:
我对给你指出一个不能解决问题的方向感到难过,所以我回去让它发挥作用。问题是您的位置参数条目未设置为接受多个标记,并且您没有填写value. 该program_options代码需要两者,否则它将不起作用。
这是适合我的完整代码:
#include <boost/program_options.hpp>
#include <iostream>
namespace po = boost::program_options;
typedef std::vector<std::string> stringvec;
std::vector<po::option> end_of_opts_parser(stringvec& args) {
std::vector<po::option> result;
stringvec::const_iterator i(args.begin());
if (i != args.end() && *i == "--") {
for (++i; i != args.end(); ++i) {
po::option opt;
opt.string_key = "pargs";
opt.value.push_back(*i); // <== here
opt.original_tokens.push_back(*i);
result.push_back(opt);
}
args.clear();
}
return result;
}
int main(int argc, char* argv[])
{
po::options_description desc("Allowed Options");
desc.add_options()
("help,h", "produce help message")
("pargs", po::value<stringvec>()->multitoken(), "positional arguments");
// and here ^^^^^^^^^^^^^
po::command_line_parser clparser(argc, argv);
clparser.extra_style_parser(end_of_opts_parser);
po::variables_map vm;
po::store(clparser.options(desc).run(), vm);
po::notify(vm);
bool const help = !vm["help"].empty();
std::cout << "help = " << help << " - ";
// in addition, you don't need to use a separate vector of strings:
stringvec const& pargs = vm["pargs"].as<stringvec>();
std::copy(pargs.begin(), pargs.end(),
std::ostream_iterator<std::string>(std::cout, ","));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行时会-h -- foo bar baz打印help = 1 - foo,bar,baz,.
| 归档时间: |
|
| 查看次数: |
2456 次 |
| 最近记录: |