命令行参数的“条件”解析

9

假设我有一个可执行程序(运行在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,但不能同时使用两者。因此,在这方面实现参数的与操作会很好。

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


这里是Boost.Program_options的示例,处理冲突和依赖选项。 - user1252091
4个回答

2

您可以对参数进行两次传递;如果选项中有-r,则重置解析器,并在添加新的强制选项后重新开始。


您还可以查看TCLAP XorHandler的工作方式,并创建自己的AndHandler


是的,我已经尝试过了,但是你仍然需要自己编写帮助屏幕(这不是问题,但有一个帮助屏幕会很好)。添加AndHandler可能是一个不错的选择。 - nils
@Nick 帮助屏幕需要特殊处理。我喜欢 Boost 程序选项的一件事情是它不会显示帮助屏幕本身,而是你必须提供自己的 --help 选项并检查并打印帮助信息。这样你就可以添加特殊选项并一次性打印所有内容。 - Some programmer dude

0
我手头有一部分TCLAP代码片段,似乎适合你正在寻找的错误处理部分,但它并不完全符合你要求的内容:
# 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。”在CLI arg解析时进行非常严格的参数检查时,使用本机C++表达式是最好的选择。

对于真正病态的情况和要求,请使用类似Boost.MSM(多状态机)的东西创建状态机。希望对你有所帮助。


0

你可以更改参数语法,使得-r接受四个连续的值。


2
这会相当令人困惑,因为这不是参数通常的工作方式。 - user308323
是的,但它们可能是不同的数据类型。据我所知,问题中提到的库仅将多个参数处理为一种类型。 - nils

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接