Java 如何让Apache CLI处理双破折号?

Java 如何让Apache CLI处理双破折号?,java,command-line-interface,apache-commons,apache-commons-cli,Java,Command Line Interface,Apache Commons,Apache Commons Cli,我查看了文档,但看不到如何让Apache Commons CLI处理通常终止选项处理的双连字符“选项” 考虑以下命令行,该命令行具有“-opt”选项,可以接受未指定的可选参数: MyProgram -opt -- param1 param2 在本例中,我希望该选项最终不带任何参数,但Apache返回“-”作为参数。如果该选项允许多个参数,则部分或全部参数将作为参数返回 下面是说明问题的示例代码: package com.lifetouch.commons.cli; import java.u

我查看了文档,但看不到如何让Apache Commons CLI处理通常终止选项处理的双连字符“选项”

考虑以下命令行,该命令行具有“-opt”选项,可以接受未指定的可选参数:

MyProgram -opt -- param1 param2
在本例中,我希望该选项最终不带任何参数,但Apache返回“-”作为参数。如果该选项允许多个参数,则部分或全部参数将作为参数返回

下面是说明问题的示例代码:

package com.lifetouch.commons.cli;

import java.util.Arrays;
import org.apache.commons.cli.*;

public class DoubleHyphen {
  private static Options options = new Options();

  public static void main(String args[]) {
    // One required option with an optional argument:
    @SuppressWarnings("static-access")
    OptionBuilder builder = OptionBuilder.isRequired(true).
            withDescription("one optional arg").
            withArgName("optArg").hasOptionalArgs(1);
    options.addOption(builder.create("opt"));

    // Illustrate the issue:
    doCliTest(new String[] { "-opt"} );
    doCliTest(new String[] { "-opt", "optArg", "param"} );
    doCliTest(new String[] { "-opt", "--", "param"} );
    // What I want is for the double-dash to terminate option processing.
    // Note that if "opt" used hasOptionalArgs(2) then "param" would be a second
    // argument to that option (rather than an application parameter).
  }

  private static void doCliTest(String[] args) {
    System.out.println("\nTEST CASE -- command line items: " + Arrays.toString(args));

    // Parse the command line:
    CommandLine cmdline = null;
    try {
        CommandLineParser parser = new GnuParser();
        cmdline = parser.parse(options, args); // using stopAtNonOption does not help
    } catch (ParseException ex) {
        System.err.println("Command line parse error: " + ex);
        return;
    }

    // Observe the results for the option and argument:
    String optArgs[] = cmdline.getOptionValues("opt");
    if (null == optArgs) {
        System.out.println("No args specified for opt");
    } else {
        System.out.println(optArgs.length + " arg(s) for -opt option: " +
                Arrays.toString(optArgs));
    }

    // Observe the results for the command-line parameters:
    String tmp = Arrays.toString(cmdline.getArgList().toArray());
    System.out.println(cmdline.getArgList().size() +
            " command-line parameter(s): " + tmp);
  }
}

为了将特殊令牌作为选项终止符处理,必须使用POSIX解析器

使用

而不是

CommandLineParser parser = new GnuParser();

您使用的是最新的Apache Commons CLI 1.2版本吗?那么下面的
PosixParser
应该可以工作。请参见sourcecode:它确实处理--(请参见第182行的私有void processNonOptionToken(字符串值,布尔stopAtNonOption))。GnuParser和PosixParser都不能正确处理--选项,尤其是当它出现在可能有可选参数的地方时。命令行“-a--b”将--作为参数添加到-a选项中,并且-b始终被视为选项(而不是参数)。这是关于StopAtNon选项设置的。我上面的测试代码可以很容易地说明这一点。您是否可以使用
OptionBuilder.withValueSeparator()
来防止此问题?这样,可选参数必须通过
=
与选项分开,解析器就不会感到困惑。如果等号不合适,还可以使用
OptionBuilder.ValueSeparator(char-sep)
指定自定义字符。我知道这并不完全是您想要实现的,但这可能是一个可行的解决方案。这将极大地改变选项的定义及其参数,并打破提交给用户的合同。以空格分隔的选项当前正在使用。不过,这可能是一种对其他人可能有效的方法。正如我在上面的OP评论中所指出的,简单地切换到PosixParser并不能解决问题。您是否尝试过同时使用
true
false
stopAtNonOption
选项?如果这没有帮助,那么ApacheCommons CLI不符合,我将自己在错误报告中提交。对于GnuParser或PosixParser,stopAtNonOption值并不重要。我上面的测试程序可以很容易地证明这一点。观察第三个测试用例的结果永不改变。为了强调这一点,请为“-opt--opt2”添加一个测试用例。还要注意,将stopAtNonOption更改为true确实会改变这样的命令行的处理方式:“-opt1 param1 arg1-opt2 arg3”。我不想彻底改变选项解析语义,我只想正确处理-,我之所以赏金是因为Unai Vivi真的在这方面做了很多工作,我对此表示感谢。但是我没有接受这个答案,因为我仍然没有一个解决方案使ApacheCommonsCLI1.2正确处理双破折号。
CommandLineParser parser = new GnuParser();