使用Boost.Program_options创建前缀命令

时间:2016-06-23 16:02:24

标签: c++ boost command-line-arguments boost-program-options

我想使用Boost.Program_options创建像strace这样的前缀程序。前缀意味着我的程序放在另一个任意command [args]之前。因此,我的程序应该接受定义的许多关键字参数/标志。第一个位置参数表示我正在添加前缀的命令。此命令本身可以跟随我不知道的任何参数组合,并且可能与我的程序的参数重叠。因此,第一个位置参数及其之后的任何内容都应该以{{1​​}}:

结尾
std::vector<std::string>

正确的用法是首先指定任何已定义的关键字 基本上以正确的形式,首先我定义的一些应该采取任意数量的预定义

我尝试了两种方法:

1)使用./foo --bar 13 command1 # Should run fine ./foo command2 positional # Should run fine ./foo --bar 13 command3 --unknown argument # Should run fine ./foo --unknown command4 # should fail ./foo --bar 13 command5 --bar 42 # Should work but set bar to 13 ./foo command6 --bar 42 # Should not set bar at all ./foo --bar 13 -- command7 --bar 42 --unknown argument # Should work

allow_unregistered

命令4,5,6

失败

2)一个无限次出现的位置选项

#include <iostream>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

int main(int argc, const char** argv)
{
    int bar = 0;
    po::options_description desc("Allowed options");

    desc.add_options()
            ("bar", po::value(&bar), "bar");


    po::variables_map vm;
    po::parsed_options parsed =
        po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
    po::store(parsed, vm);
    po::notify(vm);

    auto command = po::collect_unrecognized(parsed.options, po::include_positional);
    std::cout << "bar: " << bar << ", command:";
    for (const auto& c : command) std::cout << " " << c;
    std::cout << std::endl;
}

命令3,5,6。

失败

1 个答案:

答案 0 :(得分:2)

Boost Trac上有一项功能请求,包括补丁:https://svn.boost.org/trac/boost/ticket/6991。机票上没有多少动静,但补丁仍然适用于Boost(截至1.61.0,最新版本)。

如果你的构建系统允许,你可以将补丁应用到本地的Boost副本;否则,您可以从boost::program_options::detail::cmdlinecmdline.hppdetail/cmdline.hpp中提取cmdline.cpp到您自己的命名空间,修补该组件,并使用您的修补组件代替boost::program_options::cmdline

还有一个选项是使用boost::program_options::detail::cmdline参数破解extra_style_parser的行为:

po::detail::cmdline cmdline(argc, argv);
cmdline.set_options_description(desc);
cmdline.set_positional_options(p);
std::vector<po::detail::cmdline::style_parser> style_parsers{
    [&](auto& args) { return cmdline.parse_long_option(args); },
    [&](auto& args) { return cmdline.parse_short_option(args); }};
cmdline.extra_style_parser([&](std::vector<std::string>& args) {
    auto const current_size = args.size();
    std::vector<po::option> result;
    for (auto const& parser : style_parsers) {
        auto const next = parser(args);
        result.insert(result.end(), next.begin(), next.end());
        if (args.size() != current_size)
            return result;
    }
    if (args.size() && args[0] != "--") args.insert(args.begin(), "--");
    auto const next = cmdline.parse_terminator(args);
    result.insert(result.end(), next.begin(), next.end());
    return result;
});
po::parsed_options parsed{&desc};
parsed.options = cmdline.run();
po::store(parsed, vm);
po::notify(vm);

Example警告:这是对未记录的库内部的攻击,并且可能随时中断。