当用户只想打印使用情况时,如何避免所需选项的ParserException?

时间:2013-01-13 23:27:56

标签: java apache-commons-cli

所以我有一个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会引发异常 - 但是我希望打印我的消息并且不会抛出任何异常 - 如何解决这个问题?这会在line.hasOption("help")中引发NPE,当然:

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

5 个答案:

答案 0 :(得分:7)

改编自here

的解决方案
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);

如果有更优雅的话,我很乐意接受它

答案 1 :(得分:1)

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

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

例如:

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

使用参数完成的第一件事是确定命令是什么。为此我设置了一个TaskFactory,它查看第一个参数,剥离任何前导连字符,然后查找它是否是已知任务。我有一个'帮助'任务,让我的用户可以这样做:

$ controller -help

$ controller help

每个任务还​​有一个帮助选项,因此用户可以执行以下操作:

$ controller startall -help
但是,这可能对你没有帮助。我会发布一个替代方案。

答案 2 :(得分: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

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

答案 3 :(得分:0)

Commons CLI没有处理选项间依赖关系,正如您所发现的那样。在您的情况下,--help选项会修改seq1seq2的要求。

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

答案 4 :(得分:0)

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

Can Apache Commons CLI options parser ignore unknown command-line options?

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

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