【问题标题】:"Conditional" parsing of command-line arguments命令行参数的“条件”解析
【发布时间】:2012-12-07 00:29:16
【问题描述】:

假设我有一个可执行文件(在 mac、win 和 linux 上运行)

 a.out [-a] [-b] [-r -i <file> -o <file> -t <double> -n <int> ]

[ ] 中的参数表示它是可选的。但是,如果设置了最后一个参数 -r,则还必须提供 -i-o-t-n

有很多优秀的 C++ 库可以解析命令行参数,例如gflags (http://code.google.com/p/gflags/)、tclap (http://tclap.sourceforge.net/)、simpleopt(http://code.jellycan.com/simpleopt/)、boost.program_options (http://www.boost.org/doc/libs/1_52_0/doc/html/program_options.html) 等。但我想知道是否有一个可以让我直接编码参数之间的这些条件关系,无需手动编码错误处理

if ( argR.isSet() && ( ! argI.isSet() || ! argO.isSet() || ... ) ) ...

并手动设置--help

tclap 允许异或参数,例如允许使用 -a-b,但不能同时使用两者。所以,在那个术语中,参数的 AND 会很好。

有人知道可以做到这一点的多功能、轻量级和跨平台库吗?

【问题讨论】:

  • Here 是 Boost.Program_options 中处理冲突和依赖选项的示例。

标签: c++ command-line terminal command-line-arguments


【解决方案1】:

你想解析一个命令行吗?你可以使用simpleopt,它可以如下使用:下载simpleopt from: https://code.google.com/archive/p/simpleopt/downloads

测试: int _tmain(int argc, TCHAR * argv[]) argv可以是:1.txt 2.txt *.cpp

【讨论】:

    【解决方案2】:

    我有一部分 TCLAPsn-p 代码似乎适合您正在寻找的错误处理部分,但它与您正在寻找的内容不完全匹配:

    # include "tclap/CmdLine.h"
    
    namespace TCLAP {
    
    class RequiredDependentArgException : public ArgException {
    public:
      /**
       * Constructor.
       * \param text - The text of the exception.
       * \param parentArg - The text identifying the parent argument source
       * \param dependentArg - The text identifying the required dependent argument
       * of the exception.
       */
      RequiredDependentArgException(
        const TCLAP::Arg& parentArg,
        const TCLAP::Arg& requiredArg)
      : ArgException(
        std::string( "Required argument ") +
        requiredArg.toString() +
        std::string(" missing when the ") +
        parentArg.toString() +
        std::string(" flag is specified."),
        requiredArg.toString())
      { }
    };
    
    } // namespace TCLAP
    

    然后在TCLAP::CmdLine::parse 被调用后使用新的异常:

    if (someArg.isSet() && !conditionallyRequiredArg.isSet()) {
      throw(TCLAP::RequiredDependentArgException(someArg, conditionallyRequiredArg));
    }
    

    我记得我曾考虑扩展并添加一个额外的类来处理这个逻辑,但后来我意识到我真正想要的唯一东西是漂亮的错误报告,因为逻辑并不完全简单而且不容易浓缩(至少,不是以对下一个出现的可怜人有用的方式)。一个人为的场景阻止了我进一步追求它,大意是“如果 A 为真,则必须设置 B,但如果 D 的值为 N,则不能设置 C。”用原生 C++ 表达这样的事情是要走的路,尤其是当需要在 CLI arg 解析时进行非常严格的参数检查时。

    对于真正的病态案例和要求,请使用Boost.MSM(多状态机)之类的东西创建状态机。 HTH。

    【讨论】:

      【解决方案3】:

      您可以更改参数语法,以便 -r 连续获取四个值。

      【讨论】:

      • 不过,这会让人很困惑,因为参数通常不是这样工作的
      • 没错,但是,它们可能是不同的数据类型。据我所知,问题中提到的库(仅)将多参数处理为一种类型。
      【解决方案4】:

      你可以两次传递参数;如果-r 在选项中,则重置解析器并重新添加新的强制选项。


      您还可以研究 TCLAP XorHandler 的工作原理,并创建您自己的 AndHandler

      【讨论】:

      • 是的,我已经尝试过了,但是您仍然需要自己编写帮助屏幕代码(这不是问题,但如果有,那就太好了)。我猜,添加 AndHandler 将是一个不错的选择。
      • @Nick 无论如何,帮助屏幕都需要特殊处理。我喜欢 Boost 程序选项的一件事是它本身不显示帮助屏幕,但您必须提供自己的 --help 选项并检查并自己打印帮助。这样您就可以添加特殊选项并一次性打印出来。
      猜你喜欢
      • 2013-03-21
      • 2012-01-26
      • 2011-08-15
      • 1970-01-01
      相关资源
      最近更新 更多