7

所以我有一个Options实例,其中包括其他选项(注意isRequired()):

        options.addOption(OptionBuilder
                .withLongOpt("seq1")
                .withDescription("REQUIRED : blah blah")
                .hasArg().isRequired().create());
        options.addOption(OptionBuilder
                .withLongOpt("seq2")
                .withDescription("REQUIRED : blih blih")
                .hasArg().isRequired().create());
        options.addOption(new Option("?", "help", false,
                "print this message and exit"));

当我调用时parser.parse(args)抛出异常,如果seq1并且seq2不存在 - 但我想让它打印我的消息并且没有抛出异常 - 怎么办?这自然会引发 NPE line.hasOption("help")

CommandLine line = null;
try {
    CommandLineParser parser = new GnuParser();
    // parse the command line arguments
    line = parser.parse(options, args);
} catch (ParseException e) {
    if (line.hasOption("help")) { //NPE
        usage(0);
    }
    System.err.println("Parsing failed.  Reason: " + e.getMessage());
    usage(1);
}

private static void usage(int exitCode) {
    // automatically generate the help statement
    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("Smith Waterman", OPTIONS, true);
    System.exit(exitCode);
}
4

5 回答 5

7

从这里改编的解决方案

private static final Options OPTIONS = new Options();
private static final Options HELP_OPTIONS = new Options();
OPTIONS.addOption(OptionBuilder
        .withLongOpt("seq1")
        .withArgName("file1")
        .withDescription(
                "REQUIRED : the file containing sequence 1")
        .hasArg().isRequired().create());
// etc
final Option help = new Option("?", "help", false,
        "print this message and exit");
HELP_OPTIONS.addOption(help);
OPTIONS.addOption(help);
// later
CommandLineParser parser = new GnuParser();
CommandLine line = parser.parse(HELP_OPTIONS, args, true); // true so it
// does not throw on unrecognized options
if (line.hasOption("help")) {
    usage(0); // calls exit
}
line = parser.parse(OPTIONS, args);

如果有更优雅的东西出现,我很乐意接受

于 2013-01-16T11:23:56.993 回答
1

根据您的使用情况,这可能有用也可能没用。我的如下:

  • 我有一个包装程序(称为“控制器”)
  • 控制器可以运行许多命令(称为“任务”)
  • 每个命令都有自己独特的命令行参数集

例如:

$ controller startall -rsrc foo -dir bar -where baz

使用参数完成的第一件事是确定命令是什么。为此,我设置了一个 TaskFactory,它查看第一个参数,去掉任何前导连字符,然后查看它是否是已知任务。我有一个“帮助”任务,可以让我的用户执行以下操作:

$ controller -help

$ controller help

每个任务还​​有一个帮助选项,所以用户可以:

$ controller startall -help

不过,这可能对您没有帮助。我会发布一个替代方案。

于 2013-01-14T14:59:00.160 回答
1

我在解析之前使用了以下检查以确保-h--help否决其他所有内容。

// check if help is requested
if (Arrays.asList(args).contains("-h")
        || Arrays.asList(args).contains("--help")) {
    usage(0); // print usage with exit 0
}
// parse options

不是最好的解决方案,但它满足我的需求。

于 2015-02-16T13:58:31.213 回答
0

正如您所发现的,Commons CLI 不处理选项间依赖关系。在您的情况下,该选项修改了and--help的要求。seq1seq2

唯一真正的解决方案是使所有选项都不是必需的,并在命令行解析完成后自己进行依赖关系验证。

于 2013-01-14T04:33:23.863 回答
0

扩展您选择的解析器以忽略未知选项:

Apache Commons CLI 选项解析器可以忽略未知的命令行选项吗?

然后解析参数两次,一次用于-help参数,一次用于普通参数。第一次通过你应该传递“忽略”标志,第二次你不应该。

或者,对选项进行两次解析,一次查找-help并捕获(并忽略)MissingOptionException,然后再次使用常规参数。

于 2013-01-14T15:15:10.913 回答