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

时间:2015-12-31 16:29:39

标签: java command-line-interface apache-commons apache-commons-cli

我即将迁移一些遗留代码,以包含来自 3rd -party库的较少弃用警告。对于Apache commons-cli库(版本: 1.3.1 ),我在official JavaDoc中检测到GnuParser已弃用且应使用DefaultParser

  

自1.3以来@deprecated,使用{@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

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

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

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

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

  1. "类别" (别无其他)
  2. 但是,当我更改我的代码并通过以下方式切换到推荐的解析器时:

    CommandLineParser parser = new DefaultParser();
    

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

    1. "类别"
    2. " -gsd"
    3. " 4"
    4. 提示:我使用调试器通过返回的values变量检查org.apache.commons.cli.Option中的字段commands来验证解析过程的错误结果。

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

      我可能会监督DefaultParser的构造/用法是否存在差异?

2 个答案:

答案 0 :(得分:8)

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

首先DefaultParser通过调用返回-gst的{​​{3}}来将true视为简短选项。

到目前为止一切顺利。

现在,当决定是否将-gsd解释为-gst DefaultParser的参数值时,需要确定-gsd本身是否是一个选项(因此可以& #39; t是-gst的参数。它通过调用自己的Options.hasShortOption("-gst")来实现。然而,这会返回false,原因如果您查看代码就会变得明显:

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));
}

这会从-gst选项中提取第一个字母,从而调用返回Options.hasShortOption("g")的{​​{1}}。该代码似乎是为POSIX风格的单字母选项设计的,但是对于多字母单连字符选项(例如您正在使用的选项)而言它会被分解。

无论你转过它,false都被认为是一个简短的选项,但-gst 而不是被识别似乎对我来说是一个错误。

答案 1 :(得分:1)

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

此外,setValueSeparator(',')似乎定义了通常使用等号的内容(参见JavaDoc),即格式为“key = value”的选项,所以不是你实际看到的内容对于。

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