【问题标题】:Boost program_options partial key match提升 program_options 部分键匹配
【发布时间】:2020-10-05 06:47:33
【问题描述】:

我正在尝试使用 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;

【问题讨论】:

  • 是的,只需枚举解析的选项。如果您添加代码,我们可以显示
  • 添加了一些代码。枚举解析的选项是什么意思?

标签: c++ boost boost-program-options


【解决方案1】:

问。枚举解析后的选项是什么意思?

A. 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"

模糊匹配,听起来像是正则表达式的工作,也许?

Live On Coliru

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

【讨论】:

【解决方案2】:

answered提出的问题。但是,这确实是在颠覆 Boost Program Options 库。

手动解析相同的东西似乎更容易:

Live On Coliru

#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

请注意,任何 boost 库都不再有链接依赖。

【讨论】:

  • 谢谢,我希望有一个预制的解决方案,但似乎 boost::program_options 不是。您是否知道默认情况下会为配置文件读取进行“模糊”匹配的任何库?
  • 如果库解决了定义明确的问题,它们就存在。这个问题没有明确定义,所以我不知道您为什么期望存在解决方案。 [为了好玩,一个带有静态编译正则表达式的调整版本godbolt.org/z/cYc9Jm]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-10
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
相关资源
最近更新 更多