【问题标题】:boost::program_options config file formatboost::program_options 配置文件格式
【发布时间】:2019-01-16 20:36:12
【问题描述】:

我正在使用 boost::program_options 来加载命令行参数。现在我想另外加载一个具有相同参数集的配置文件。我以非常标准的方式使用它:

ifstream ifs(filename.c_str());
if (ifs) {
    po::store(po::parse_config_file(ifs, optionsDescription), vm);
    po::notify(vm);
}

问题是 parse_config_file 接受以下标准格式的 ini 文件:

key1=value
key2 = value

但我的文件没有使用“等号”来分隔键和值,而只使用空格和/或制表符,如下所示:

key1 value
key2  value

出于兼容性原因,我需要保留此格式。有没有办法通过 boost program_options 实现这一点? 我找到了 command_line parses 的样式选项,但 parse_config_file 似乎没有这样的选项。

【问题讨论】:

  • 也许您可以读取您的文件并将不同的选项存储在内存中(例如argv)并将其提供给command_line_parser
  • 如果没有标准支持的方式,可能需要类似的东西。存储在内存中并重新格式化为标准 ini 格式(添加等号而不是每行的第一个分隔符)或提供命令行解析器(在每行前面添加减号)。不是很好,但如果没有其他选项可用。

标签: c++ boost delimiter file-format boost-program-options


【解决方案1】:

根据source code,boost 似乎明确地寻找= 符号。

因此没有直接的方法来处理您的文件格式。您可能需要更改 boost 源或将文件加载到内存并将值作为命令行输入处理。

else if ((n = s.find('=')) != string::npos) {
    string name = m_prefix + trim_ws(s.substr(0, n));
    string value = trim_ws(s.substr(n+1));

    bool registered = allowed_option(name);
    if (!registered && !m_allow_unregistered)
        boost::throw_exception(unknown_option(name));

    found = true;
    this->value().string_key = name;
    this->value().value.clear();
    this->value().value.push_back(value);
    this->value().unregistered = !registered;
    this->value().original_tokens.clear();
    this->value().original_tokens.push_back(name);
    this->value().original_tokens.push_back(value);
    break;

}

【讨论】:

  • 谢谢你,miradham。所以我将它加载到内存并使用 command_line_parser 处理它。必须有一些修剪和内部空白重复处理(std::remove、unique、isspace...),在尊重引号的同时拆分(boost tokenizer 和 escaped_list_separator),添加“--”以使其成为 cmd 格式等,所以没有我希望的那么优雅,但它似乎正在工作。
【解决方案2】:

我需要类似的东西,但输入配置文件是一个基本的 CSV 文件(即不支持处理包含逗号的值)。

根据 miradham 上面写的内容,我的解决方案是通过 filtering_istream 传递输入文件流,并应用一个简单的正则表达式过滤器,将 ',' 翻译成 '='。

如果以后我们需要用逗号添加值,那么我可能必须实现自己的filtering_istream(我知道它是一个模板)来处理这种更复杂的情况。

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/regex.hpp>
#include <boost/program_options.hpp>
#include <boost/regex.hpp>

...

// do we have a config file?
if (vm.count("config"))
{
    std::ifstream fConfig{ vm["config"].as<std::string>().c_str() };
    if (fConfig)
    {
        // prep_config = filtered stream, replacing ',' with '='
        boost::iostreams::filtering_istream prep_config;
        prep_config.push(boost::iostreams::regex_filter{ boost::regex{","}, "="});
        prep_config.push(fConfig);

        po::store(parse_config_file( prep_config, desc), vm);
        po::notify(vm);
    }
    else
    {
        std::cerr << "Could not open the configuration file - ignoring.\n";
    }
}
// drop through to the main configuration interpretation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多