为什么默认解析器(使用commons-cli)在未识别选项时不会抛出异常?

时间:2016-10-17 08:57:32

标签: java apache-commons-cli

如果指定为程序参数的选项无效(在预定义选项列表中不可用),我希望有一条打印的用法帮助消息。

      CommandLineParser parser = new BasicParser();
    try {
        CommandLine line = parser.parse(getOptions(), args);
    }
    catch( ParseException exp ) {
        getLogger().info("Invalid command line option name. "+exp.getMessage());
        HelpFormatter hf = new HelpFormatter();
        hf.printHelp("destDir", getOptions());
        return false;
    }       
    return true;

我输入参数'测试'串。我在想,无效选项会导致解析器抛出ParseException,但事实并非如此。我怎样才能实现这种行为?这个图书馆可以吗?现在它只是省略了无效的参数。

更新 实际上,当选项有一个' - '字首。所以' -Test'导致抛出异常,但是'测试'不。无论如何我的问题仍然有效,如何强制解析器在无效参数

上抛出异常

3 个答案:

答案 0 :(得分:1)

命令行有两种类型的条目,而不是程序名称,选项(用---指定)和我将调用的参数(可能有更好的名称,但我不知道它是什么!)没有前缀。例如,对于ls

ls -la foo

选项为-l-a,参数为foo(要列出的目录)。当您使用commons-cli解析命令行时,关心选项,它会忽略其他所有内容。这就是为什么如果你添加Test(不是一个选项)它就不会失败,但如果添加-Test则会失败。

答案 1 :(得分:0)

尽管adamreeve提供的答案非常好并且我接受了,但我决定扩展默认解析器功能以防止输入无效选项,即使没有“ - ”或“ - ”符号也是如此。我制作了自己的自定义解析器:

public class StrictParser extends Parser {

    @Override
    protected String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption) {
        return arguments;
    }

    @Override
    public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException {

        CommandLine cmd = null;
        List<String> tokenList = Arrays.asList(flatten(getOptions(), arguments, stopAtNonOption));
        ListIterator<String> iterator = tokenList.listIterator();

        boolean eatTheRest = false;
        setOptions(options);
        cmd = super.parse(options, arguments, stopAtNonOption);

        while (iterator.hasNext()) {
            String token = (String) iterator.next();
            if (!token.startsWith("--") && !token.startsWith("-")) {
                if (stopAtNonOption) {
                        throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token);
                }
            } else {
                eatTheRest = true;
            }

            if (eatTheRest) {
                iterator.next();
            }
        }
        return cmd;
    }
}

在此解决方案中,任何没有“ - ”或“ - ”的cli参数都会抛出UnrecognizedOptionException。这不是完美的解决方案,但它展示了如何完成,并且可以成为其他解决方案的良好起点。例如,我们可以接受没有' - '和' - '的选项,但检查该选项是否正确。然后我们需要改变

        if (stopAtNonOption) {
                throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token);
        }

        if (stopAtNonOption) {                  
            if(!getOptions().hasOption(token)){                     
                throw new UnrecognizedOptionException(
                        "Unrecognized option: " + token, token);
            }
        }

(忽略这个丑陋的三个嵌套ifs;)) 这也只接受每个选项一个参数,但正如我所提到的,它是对默认解析器实现其他修改的唯一起点

答案 2 :(得分:-1)

是的,你可以,你必须创建自定义的例外:

public class ParseException extends Exception{
        ParseException(String msg){
             super(msg);  
        }
}

进入代码:

CommandLineParser parser = new BasicParser();
    try {
        CommandLine line = parser.parse(getOptions(), args);
    }
    catch( Exception exp ) {
       throw new ParseException("Invalid Arguments");
    }       
    return true;

以上方法应抛出

throws ParseException

因此,如果传递无效参数,则其调用者将获得ParseException