Boost program_options 部分键匹配
Boost program_options partial key match
我正在尝试使用 Boost::program_options 读取配置文件。配置文件如下所示:
hier.arch.y.option_name = 0x5
another.hier.archy.setting_name = 0x1E
我希望能够仅通过 "option_name" 或 "setting_name" 进行搜索。我不太担心重复项,但如果有一种方法可以选择匹配 2 个子字符串(即 "another" + "setting_name"),那也很棒。
有没有办法让program_options根据子字符串进行匹配?
代码示例:
namespace po = boost::program_options;
po::options_description cmd_opts{"Options"};
po::options_description config_file_opts;
cmd_opts.add_options()
("help,h", "Help message")
("config_help", "List of configurations available in config file");
po::variables_map vm;
po::store(parse_command_line(argc, argv, combined_opts), vm);
auto parsed_opts = po::parse_config_file<char>(vm.["config_file"].as<std::string>);
po::store(parsed_opts, vm);
配置文件:
foo.bar.setting0 = 0x5
foo.notbar.setting1 = 0x6
bar.notfoo.setting2 = 0x5E
我想分配以下选项:
int setting0;
int setting1;
int setting2;
Q. What does enumerate the parsed options mean?
一个。 Live On Coliru
for (auto& opt : parsed_opts.options) {
for (auto& val : opt.value) {
std::cout
<< std::quoted(opt.string_key) << "\t-> "
<< std::quoted(val) << std::endl;
}
}
打印
"foo.bar.setting0" -> "0x5"
"foo.notbar.setting1" -> "0x6"
"bar.notfoo.setting2" -> "0x5E"
模糊匹配,听起来像是正则表达式工作,也许吧?
int setting0 = 0, setting1 = 0, setting2 = 0;
struct { int& target; boost::regex re; }
fuzzy_opt_desc[] = {
{ setting0, boost::regex{R"(bar\.setting0$)"} },
{ setting1, boost::regex{R"(^foo\..*?setting1$)"} },
{ setting2, boost::regex{R"(setting2$)"} },
};
for (auto& opt : parsed_opts.options) {
for (auto const& desc : fuzzy_opt_desc) {
if (boost::regex_search(opt.string_key, desc.re)) {
for (auto& val : opt.value) {
desc.target = std::stoul(val, nullptr, 16);
std::cout
<< std::quoted(opt.string_key) << "\t-> "
<< desc.target << std::endl;
}
}
} }
std::cout << "Finally: " << setting0 << ", " << setting1 << ", " << setting2 << "\n";
版画
"foo.bar.setting0" -> 5
"foo.notbar.setting1" -> 6
"bar.notfoo.setting2" -> 94
Finally: 5, 6, 94
我提出的问题。然而,这确实是在颠覆Boost Program Options库。
手动解析相同的东西似乎更容易:
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/xpressive/xpressive_dynamic.hpp>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
auto parse_cfg(std::string fname) {
std::multimap<std::string, std::string> map;
std::ifstream ifs(fname);
std::string const cfg(std::istreambuf_iterator<char>(ifs), {});
using namespace boost::spirit::x3;
phrase_parse(begin(cfg), end(cfg),
-(lexeme[+(graph - '=')] >> '=' >> lexeme[+~char_("\r\n")]) %
eol,
blank, map);
return map;
}
int main() {
auto map = parse_cfg("test.cfg");
int setting0 = 0, setting1 = 0, setting2 = 0;
using boost::xpressive::sregex;
struct { int& target; sregex re; } fuzzy_opt_desc[] = {
{ setting0, sregex::compile(R"(bar\.setting0$)") },
{ setting1, sregex::compile(R"(^foo\..*?setting1$)") },
{ setting2, sregex::compile(R"(setting2$)") },
};
for (auto& [key, val] : parse_cfg("test.cfg")) {
for (auto& [target,re] : fuzzy_opt_desc) {
if (regex_search(key, re)) {
target = std::stoul(val, nullptr, 16);
std::cout << std::quoted(key) << "\t-> " << target << std::endl;
}
}
}
std::cout << "Finally: " << setting0 << ", " << setting1 << ", " << setting2 << "\n";
}
版画
"bar.notfoo.setting2" -> 94
"foo.bar.setting0" -> 5
"foo.notbar.setting1" -> 6
Finally: 5, 6, 94
Note that there is no link dependency on any boost library any more.
我正在尝试使用 Boost::program_options 读取配置文件。配置文件如下所示:
hier.arch.y.option_name = 0x5
another.hier.archy.setting_name = 0x1E
我希望能够仅通过 "option_name" 或 "setting_name" 进行搜索。我不太担心重复项,但如果有一种方法可以选择匹配 2 个子字符串(即 "another" + "setting_name"),那也很棒。
有没有办法让program_options根据子字符串进行匹配?
代码示例:
namespace po = boost::program_options;
po::options_description cmd_opts{"Options"};
po::options_description config_file_opts;
cmd_opts.add_options()
("help,h", "Help message")
("config_help", "List of configurations available in config file");
po::variables_map vm;
po::store(parse_command_line(argc, argv, combined_opts), vm);
auto parsed_opts = po::parse_config_file<char>(vm.["config_file"].as<std::string>);
po::store(parsed_opts, vm);
配置文件:
foo.bar.setting0 = 0x5
foo.notbar.setting1 = 0x6
bar.notfoo.setting2 = 0x5E
我想分配以下选项:
int setting0;
int setting1;
int setting2;
Q. What does enumerate the parsed options mean?
一个。 Live On Coliru
for (auto& opt : parsed_opts.options) {
for (auto& val : opt.value) {
std::cout
<< std::quoted(opt.string_key) << "\t-> "
<< std::quoted(val) << std::endl;
}
}
打印
"foo.bar.setting0" -> "0x5"
"foo.notbar.setting1" -> "0x6"
"bar.notfoo.setting2" -> "0x5E"
模糊匹配,听起来像是正则表达式工作,也许吧?
int setting0 = 0, setting1 = 0, setting2 = 0;
struct { int& target; boost::regex re; }
fuzzy_opt_desc[] = {
{ setting0, boost::regex{R"(bar\.setting0$)"} },
{ setting1, boost::regex{R"(^foo\..*?setting1$)"} },
{ setting2, boost::regex{R"(setting2$)"} },
};
for (auto& opt : parsed_opts.options) {
for (auto const& desc : fuzzy_opt_desc) {
if (boost::regex_search(opt.string_key, desc.re)) {
for (auto& val : opt.value) {
desc.target = std::stoul(val, nullptr, 16);
std::cout
<< std::quoted(opt.string_key) << "\t-> "
<< desc.target << std::endl;
}
}
} }
std::cout << "Finally: " << setting0 << ", " << setting1 << ", " << setting2 << "\n";
版画
"foo.bar.setting0" -> 5
"foo.notbar.setting1" -> 6
"bar.notfoo.setting2" -> 94
Finally: 5, 6, 94
我
手动解析相同的东西似乎更容易:
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/xpressive/xpressive_dynamic.hpp>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
auto parse_cfg(std::string fname) {
std::multimap<std::string, std::string> map;
std::ifstream ifs(fname);
std::string const cfg(std::istreambuf_iterator<char>(ifs), {});
using namespace boost::spirit::x3;
phrase_parse(begin(cfg), end(cfg),
-(lexeme[+(graph - '=')] >> '=' >> lexeme[+~char_("\r\n")]) %
eol,
blank, map);
return map;
}
int main() {
auto map = parse_cfg("test.cfg");
int setting0 = 0, setting1 = 0, setting2 = 0;
using boost::xpressive::sregex;
struct { int& target; sregex re; } fuzzy_opt_desc[] = {
{ setting0, sregex::compile(R"(bar\.setting0$)") },
{ setting1, sregex::compile(R"(^foo\..*?setting1$)") },
{ setting2, sregex::compile(R"(setting2$)") },
};
for (auto& [key, val] : parse_cfg("test.cfg")) {
for (auto& [target,re] : fuzzy_opt_desc) {
if (regex_search(key, re)) {
target = std::stoul(val, nullptr, 16);
std::cout << std::quoted(key) << "\t-> " << target << std::endl;
}
}
}
std::cout << "Finally: " << setting0 << ", " << setting1 << ", " << setting2 << "\n";
}
版画
"bar.notfoo.setting2" -> 94
"foo.bar.setting0" -> 5
"foo.notbar.setting1" -> 6
Finally: 5, 6, 94
Note that there is no link dependency on any boost library any more.