Java 为什么默认解析器(使用commons cli)在无法识别选项时不引发异常?

Java 为什么默认解析器(使用commons cli)在无法识别选项时不引发异常?,java,apache-commons-cli,Java,Apache Commons Cli,当指定为程序参数的选项无效(在预定义选项列表中不可用)时,我希望打印一条用法帮助消息 我键入参数“Test”字符串。我在想,无效选项会导致解析器抛出ParseException,但事实并非如此。我怎样才能做到这一点?这个图书馆有可能吗?现在它只是一个无效的参数 更新 实际上,当选项的前缀为“-”时,它会引发异常。所以“-Test”会引发异常,但“Test”不会。无论如何,我的问题仍然有效,如何强制解析器对无效参数抛出异常是的,您可以,您必须创建自定义异常,如: public class Pars

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

我键入参数“Test”字符串。我在想,无效选项会导致解析器抛出ParseException,但事实并非如此。我怎样才能做到这一点?这个图书馆有可能吗?现在它只是一个无效的参数

更新
实际上,当选项的前缀为“-”时,它会引发异常。所以“-Test”会引发异常,但“Test”不会。无论如何,我的问题仍然有效,如何强制解析器对无效参数抛出异常

是的,您可以,您必须创建自定义异常,如:

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

是的,您可以创建自定义异常,如:

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

因此,它的调用者if pass invalid参数将获得ParseException

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

ls-lafoo


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

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

ls-lafoo


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

虽然提供的答案很好,我也接受,但我决定扩展默认解析器功能,以防止键入无效选项,即使没有“-”或“--”符号。我制作了自己的自定义解析器:

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

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

虽然提供的答案很好,我也接受它,但我决定扩展默认解析器功能,以防止在没有“-”或“---”符号的情况下键入无效选项。我制作了自己的自定义解析器:

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

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

您的解决方案更像是定义新的异常。但在我的例子中,ParseException不是从parse方法抛出的,当args包含无效选项时。@ArturSkrzydło请仔细阅读答案,答案的第二部分包含修改后的代码,第三部分显示方法调用的更改。您创建了新异常,并在从parse方法抛出ParseException时抛出它。在这种情况下,它没有任何意义,因为我在定义无效参数时从未到达catch语句。@ArturSkrzydł现在看到答案,如果parse get exception它将抛出ParseException再次查看我的问题-'我在想,无效选项会导致解析器抛出ParseException,这意味着当我键入无效的选项名时,不会抛出ParseException。所以你的解决方案毫无意义。另外,重新引用异常的意义是什么。我可以尝试使用catch语句,并在方法声明的“throws”中定义它。您的解决方案更像是定义新的异常。但在我的例子中,ParseException不是从parse方法抛出的,当args包含无效选项时。@ArturSkrzydło请仔细阅读答案,答案的第二部分包含修改后的代码,第三部分显示方法调用的更改。您创建了新异常,并在从parse方法抛出ParseException时抛出它。在这种情况下,它没有任何意义,因为我在定义无效参数时从未到达catch语句。@ArturSkrzydł现在看到答案,如果parse get exception它将抛出ParseException再次查看我的问题-'我在想,无效选项会导致解析器抛出ParseException,这意味着当我键入无效的选项名时,不会抛出ParseException。所以你的解决方案毫无意义。另外,重新引用异常的意义是什么。我可以只使用ommit try catch语句,并在方法声明中的“throws”中定义它。好吧,我理解这一点,但我认为在commons cli库中,我可以验证所有命令行,但据我所知:(这就是为什么您经常可以知道什么时候使用commons cli—因为一切都是一个
--
选项:)好的,我理解这一点,但我认为在commons cli库中,我可以验证所有命令行,但据我所知,这还不够:(这就是为什么您经常可以知道某些东西何时使用commons cli的原因,因为一切都是
--
选项:)