2

有许多众所周知的命令行参数解析器,例如 argp 或 C++ 的 boost::program_options 的一个子集。

例如,我最近尝试写一个让我解析 C++ 中的简单场景,如下所示:

int main (int argc, char *argv[]) {
    auto state = parse (argc, argv);
    const auto foo  = mandatory<int>            (state, {'f', "foo"});
    const auto bar  = optional_with_default<int>(state, {'b', "bar"}, 42);
    const auto frob = optional<std::string>     (state, {'F', "frob"});
    if (!frob) {
        ...
    }
}

但很快发现解析与位置无关的标志并非易事(例如-fgx,将与 相同-f -xg),然后在混合中抛出具有值 args 的与位置无关的标志变得非常重要(例如tar -xvzf frob.tar.gz)。

只有经验主义才能使问题变得明显。例如,我没有找到任何关于此搜索的内容。

您知道有关该主题的任何好的资源吗?你自己的最佳实践是什么?


注意:尽管我命名了一些 C++ 示例,但这个问题应该与语言无关。我要求算法和一般建议。

4

1 回答 1

0

我认为,如果您正在编写一个没有声明性部分的命令行解析器(如示例中),并且允许对标志/短选项进行分组(-xf将与 相同-x -f),那么您必须以某种方式强制执行客户端的排序来电。

考虑例如(假设它是对 unixtar程序的有效调用):

tar -vfxul.tar -x

在这里,您有以下选项:

x
v
f=xul.tar

如果您首先测试x标志(p 代码),

state = parse(argc, argv)
x_set = flag (state, 'x')
...
filename = mandatory (state, 'f' or "filename")

你在回答这个问题时遇到了麻烦:哪个x

tar -vfxul.tar -x
       ^        ^
       x?       x?

因为解析器还不知道该filename选项,它可能会假设在 中vfxul.tar,每个单独的字符 ( v, x, u, ...) 都可能是要识别的标志。

所以我认为你现在最好的猜测(不诉诸简单的人工智能或一些复杂的启发式方法)就是第一次出现x.

我相信您应该禁止在解析带有值的短选项后解析任何标志选项:

state = parse(argc, argv)
x_set = flag (state, 'x')
...
filename = mandatory (state, 'f' or "filename") // THROW ERROR HERE!

这迫使您进入一种情况,您必须将您的代码按特定顺序处理,这更加降低了此类库的适用性,因此这实际上仅适用于一个非常简单的情况解析器,其中您有一个非相互依赖的参数列表.

注意:您只需要在可以使用短选项或允许标志/短选项分组的情况下对解析进行重新排序。


来源

  • 经验主义
于 2012-07-10T13:45:47.687 回答