#java #apache-commons #apache-commons-cli
#java #apache-commons #apache-commons-cli
Вопрос:
Я пишу Java-приложение, которое принимает аргументы командной строки, которые обрабатываются с помощью Apache Commons CLI с GnuParser. По причинам, в которые не интересно вдаваться, я бы хотел, чтобы он молча игнорировал неизвестные параметры командной строки вместо того, чтобы вызывать исключение ParseException, но я не вижу способа сделать это. Я вижу, что в GnuParser.parse() есть логическая опция stopAtNonOption, но то, что я хочу, больше похоже на ignoreAtNonOption, где он сохранит параметры обработки после обнаружения неизвестного токена.
Я мог бы реализовать свой собственный анализатор для достижения этой цели, но я удивлен, что в него не встроена эта функциональность, поэтому я подумал, что проверю, прежде чем идти по этому пути.
Пример кода для того, о чем я говорю:
try {
CommandLine commandLine = parser.parse(options, args);
// stopAtNonOption set to true (below) is also not what I want
// CommandLine commandLine = parser.parse(options, args, true);
} catch (ParseException e) {
LOG.error("error parsing arguments", e);
throw new RuntimeException(e);
}
Ответ №1:
У меня это работает (другие анализаторы тоже могут быть производными):
public class ExtendedGnuParser extends GnuParser {
private boolean ignoreUnrecognizedOption;
public ExtendedGnuParser(final boolean ignoreUnrecognizedOption) {
this.ignoreUnrecognizedOption = ignoreUnrecognizedOption;
}
@Override
protected void processOption(final String arg, final ListIterator iter) throws ParseException {
boolean hasOption = getOptions().hasOption(arg);
if (hasOption || !ignoreUnrecognizedOption) {
super.processOption(arg, iter);
}
}
}
Комментарии:
1. Это прекрасно, спасибо! Кстати, это должно быть замечанием для всех разработчиков API относительно того, почему вы абсолютно точно не хотите делать свои классы API окончательными. Почему? Потому что вы недостаточно умны, чтобы выяснить все способы, которыми клиентский код хотел бы повторно использовать ваши материалы.
2. Я сделал то же самое для BasicParser. Сработало как по волшебству!. Определенно следует добавить в cli API.
3. Теперь это устарело :(.
4. @JamesE.Ervin Справедливое замечание: окончательное, но вместо расширения вы всегда можете использовать шаблон делегирования: en.wikipedia.org/wiki/Delegation_pattern
5. Что, если я хочу иметь доступ к игнорируемым параметрам во время выполнения после синтаксического анализа?
Ответ №2:
Как упоминалось в комментарии, принятое решение больше не подходит, поскольку processOption
метод устарел и удален.
Вот мое решение:
public class ExtendedParser extends DefaultParser {
private final ArrayList<String> notParsedArgs = new ArrayList<>();
public String[] getNotParsedArgs() {
return notParsedArgs.toArray(new String[notParsedArgs.size()]);
}
@Override
public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException {
if(stopAtNonOption) {
return parse(options, arguments);
}
List<String> knownArguments = new ArrayList<>();
notParsedArgs.clear();
boolean nextArgument = false;
for (String arg : arguments) {
if (options.hasOption(arg) || nextArgument) {
knownArguments.add(arg);
} else {
notParsedArgs.add(arg);
}
nextArgument = options.hasOption(arg) amp;amp; options.getOption(arg).hasArg();
}
return super.parse(options, knownArguments.toArray(new String[knownArguments.size()]));
}
}
По сравнению с решением, предложенным Pascal, он также проверяет наличие параметров с аргументами и сохраняет не проанализированные аргументы в отдельном списке.
Ответ №3:
Это невозможно с CLI Commons. Но может быть другой способ достичь ожидаемого результата, если вы предоставите более подробную информацию о вашем варианте использования.
Ответ №4:
Я очень плохой разработчик, и я делаю это, чтобы сломать код:
public class EasyPosixParser extends PosixParser {
@Override
protected void processOption(String arg, ListIterator iter) throws ParseException
{
try {
super.processOption(arg, iter);
} catch (ParseException e) {
// do nothing
}
}
}
в вашем основном коде вы делаете:
CommandLineParser commandlineParser = new EasyPosixParser();