如何使用Boost.Program_options实现子命令?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (77)

我想实现子程序到我的程序。我还需要为不同的子命令提供不同的参数选项。使用Boost.Program_options执行此操作的最佳方法是什么?

子命令在svn,git和apt-get等程序中使用。

例如在GIT中,一些可用的子命令是:

git status  
git push  
git add  
git pull  

我的问题基本上和这个人一样:http : //boost.2283326.n4.nabble.com/subcommands-with-program-options-like-svn-command-td2585537.html

提问于
用户回答回答于

如果我正确理解问题,则需要解析以下形式的命令行选项:

[--generic-option ...] cmd [--cmd-specific-option ... ] 

这是我的示例解决方案。为了清楚起见,我将忽略任何验证代码,但希望您可以看到它将如何相当简单地添加。

在这个例子中,我们有“ls”子命令,可能还有其他的。每个子命令都有一些特定的选项,另外还有一些通用选项。所以让我们从解析通用选项和命令名开始。

po::options_description global("Global options");
global.add_options()
    ("debug", "Turn on debug output")
    ("command", po::value<std::string>(), "command to execute")
    ("subargs", po::value<std::vector<std::string> >(), "Arguments for command");

po::positional_options_description pos;
pos.add("command", 1).
    add("subargs", -1);

po::variables_map vm;

po::parsed_options parsed = po::command_line_parser(argc, argv).
    options(global).
    positional(pos).
    allow_unregistered().
    run();

po::store(parsed, vm);

请注意,我们为命令名称创建了一个位置选项,并为命令选项创建了多个位置选项。

现在我们分支到相关的命令名并重新解析。我们不是传入原始文件argcargv而是以字符串数组的形式传递未识别的选项。该collect_unrecognized函数可以提供这一点 - 我们所要做的就是删除(位置)命令名并重新解析相关的命令options_description

std::string cmd = vm["command"].as<std::string>();
if (cmd == "ls")
{
    // ls command has the following options:
    po::options_description ls_desc("ls options");
    ls_desc.add_options()
        ("hidden", "Show hidden files")
        ("path", po::value<std::string>(), "Path to list");

    // Collect all the unrecognized options from the first pass. This will include the
    // (positional) command name, so we need to erase that.
    std::vector<std::string> opts = po::collect_unrecognized(parsed.options, po::include_positional);
    opts.erase(opts.begin());

    // Parse again...
    po::store(po::command_line_parser(opts).options(ls_desc).run(), vm);

请注意,我们variables_map对命令特定的选项使用了与通用选项相同的选项。由此我们可以执行相关操作。

这里的代码段来自一个可编译的源文件,其中包含一些单元测试。你可以在这里找到它。请随意下载并使用它。

用户回答回答于

可以使用位置选项从命令行取得子命令名称- 请参阅本教程

似乎没有任何对子命令的内置支持 - 需要allow_unregistered在顶级解析器上设置选项,查找命令名称,然后通过第二个解析器运行它以获取任何子命令特定的选项。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励