Почему парсер по умолчанию (использующий 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' вызывает исключение, а 'Test' - нет. Мой вопрос в любом случае остается в силе, как заставить парсер выдавать исключение на неверный параметр
3 ответа
Командные строки имеют два типа ввода, отличные от имени программы, Параметры (которые указываются с -
или же --
) и то, что я назову параметрами (которые, вероятно, имеют лучшее имя, но я не знаю, что это такое!), которые не имеют префикса. Например, для ls
:
ls -la foo
Варианты -l
а также -a
и параметр foo
(каталог для списка). Когда вы анализируете командную строку с помощью commons-cli, она заботится только о параметрах, она игнорирует все остальное. Вот почему он не потерпит неудачу, если вы добавите Test
(не вариант), но если вы добавляете -Test
,
Хотя ответ от 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;)) Это также принимает только один аргумент для каждой опции, но, как я уже говорил, это только отправная точка для реализации других модификаций парсера по умолчанию
Да, вы можете создать собственное исключение, например:
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