为什么在使用 DefaultParser 而不是 GnuParser 时检测到的 CLI 选项不同?

我即将迁移一些遗留代码,以包含来自第三方库的较少弃用的警告。对于Apache库(版本:1.3.1),我在官方JavaDoc中检测到已弃用,应该改用:commons-cliGnuParserDefaultParser

@deprecated自 1.3 起,请改用{@link DefaultParser}

但是,以下代码段将按预期方式停止工作:

Options options = new Options();    
Option optionGSTypes = new Option(
        "gst","gs-types", true,
        "the supported types, comma-separated: article, category, template, all");
optionGSTypes.setArgs(3);
optionGSTypes.setValueSeparator(',');
options.addOption(optionGSTypes);

// ... other options

// parsed option values are correct, yet this is deprecated
CommandLineParser parser = new GnuParser(); 
CommandLine commands = parser.parse(options, args);

// ... interpret parsed 'commands' and related actual values via CLI

请注意,此处用于定义自定义分隔符 char,以使 CLI 能够支持 sevaral gst 类型(请参阅代码段)。setValueSeparator(','),

作为输入,以下程序参数用于调用 CLI:

java -jar MyCLI.jar -gst category -gsd 4

显然,在 gsd 参数之后可能还添加了其他几个参数。对于不使用分隔符的“gst”参数,预期和正确解析的选件是(通过):GnuParser

  1. “类别”(仅此而已)

但是,当我更改代码并通过以下方式切换到推荐的解析器时:

CommandLineParser parser = new DefaultParser();

生成的解析值被错误地检测为:

  1. “类别”
  2. “-gsd”
  3. "4"

提示:我使用调试器通过返回的变量检查中的字段来验证解析过程的错误结果。valuesorg.apache.commons.cli.Optioncommands

我的期望是,解析器的内部更改不应该产生不同的结果,因为这会破坏现有的代码。有没有人在切换到和几个选项值和自定义分隔符时遇到过与Apache Commons-CLI相同的行为?DefaultParser

我可能已经监督的构造/使用是否有差异?DefaultParser


答案 1

单步执行 的代码,这似乎是一个错误。DefaultParser

首先通过调用 Options.hasShortOption(“-gst”) 来识别为短选项,该选项返回 。DefaultParser-gsttrue

目前为止,一切都好。

现在,当涉及到决定是否解释为参数值时,需要弄清楚是否本身就是一个选项(因此不能成为参数)。它通过调用自己的 isShortOption(“-gsd”) 来做到这一点。但是,如果您查看代码,则返回的原因很明显:-gsd-gstDefaultParser-gsd-gstfalse

private boolean isShortOption(String token)
{
    // short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
    return token.startsWith("-") && token.length() >= 2 && 
           options.hasShortOption(token.substring(1, 2));
}

这将从选项中提取第一个字母,因此调用返回 .该代码似乎适用于POSIX样式的单字母选项,但它会分解为多字母单连字符选项,例如您正在使用的那些选项。-gstOptions.hasShortOption("g")false

无论你如何转动它,被识别为一个简短的选项,但没有得到认可对我来说似乎是一个错误。-gst-gsd


答案 2

我认为问题可能在于调用,根据JavaDoc,它指示commons-cli“设置此选项可以采用的参数值的数量”,即您指示commons-cli将接下来的三个commnadline参数作为“gst”参数的参数。optionGSTypes.setArgs(3);

此外,似乎定义了等号通常用于什么(参见JavaDoc),即格式为“key=value”的选项,因此不是您实际要查找的。setValueSeparator(',')

在你的情况下,我认为最简单的选择是将选项参数指定为简单字符串并自己进行解析。通过这种方式,您可以完全控制允许哪些值,还可以提供更好的错误消息。