Почему определенные параметры CLI отличаются при использовании DefaultParser вместо GnuParser?
Я собираюсь перенести некоторый старый код, чтобы содержать менее устаревшие предупреждения от сторонних библиотек. Для библиотеки Apache commons-cli
(версия: 1.3.1) Я обнаружил в официальном JavaDoc , что GnuParser
устаревший и DefaultParser
следует использовать вместо:
@deprecated с 1.3, используйте {@link DefaultParser}
вместо
Однако следующий фрагмент кода перестает работать как ожидалось:
Options options = new Options();
Option optionGSTypes = new Option(
"gst","gs-types", true,
"the supported types, comma-separated: article, category, template, all");
optionGSTypes.setArgs(3);
optionGSTypes.setValueSeparator(',');
options.addOption(optionGSTypes);
// ... other options
// parsed option values are correct, yet this is deprecated
CommandLineParser parser = new GnuParser();
CommandLine commands = parser.parse(options, args);
// ... interpret parsed 'commands' and related actual values via CLI
Обратите внимание, что setValueSeparator(',')
используется здесь для определения пользовательского разделителя char ,
, чтобы позволить CLI поддерживать sevaral gst-типы (см. фрагмент кода).
В качестве входных данных для вызова CLI используются следующие аргументы программы:
java -jar MyCLI.jar -gst category -gsd 4
Очевидно, что после параметра gsd также может быть добавлено несколько других аргументов. Ожидаемые и правильно разобранные параметры для использования аргумента "gst" без разделителя (через GnuParser
):
- "категория" (и ничего больше)
Однако, когда я меняю свой код и переключаюсь на рекомендуемый синтаксический анализатор через:
CommandLineParser parser = new DefaultParser();
результирующие, проанализированные значения обнаруживаются некорректно как:
Подсказка: я использовал отладчик, чтобы проверить неверный результат процесса синтаксического анализа, проверив поле values
в org.apache.commons.cli.Option
с помощью возвращаемой переменной commands
.
Мое ожидание будет состоять в том, что внутреннее изменение анализатора должно не давать разные результаты, так как это нарушает существующий код. Кто-нибудь сталкивался с тем же поведением с Apache Commons-CLI при переключении на DefaultParser
и несколькими значениями параметров и пользовательскими разделителями?
Есть ли разница в конструкции/использовании DefaultParser
, которую я мог бы контролировать?
Ответы
Ответ 1
Выполняя код DefaultParser
, это похоже на ошибку.
Сначала DefaultParser
распознает -gst
как короткий вариант, вызывая Options.hasShortOption("-gst")
, который возвращает true
.
Пока все хорошо.
Теперь, когда дело доходит до того, следует ли интерпретировать -gsd
как значение аргумента для -gst
DefaultParser
, нужно выяснить, является ли -gsd
самим вариантом (и поэтому не может быть аргументом для -gst
). Он делает это, вызывая собственный isShortOption("-gsd")
. Однако это возвращает false
по причинам, которые становятся очевидными, если вы посмотрите на код:
private boolean isShortOption(String token)
{
// short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
return token.startsWith("-") && token.length() >= 2 &&
options.hasShortOption(token.substring(1, 2));
}
Здесь извлекается первая буква из опции -gst
, поэтому вызывается Options.hasShortOption("g")
, которая возвращает false
. Этот код, похоже, предназначен для работы с однобуквенными параметрами в стиле POSIX, но он разбивается на многобуквенные варианты с одним дефем, такие как те, которые вы используете.
Однако вы его включаете, -gst
становится признанным в качестве короткой опции, но -gsd
не распознается, как ошибка для меня.
Ответ 2
Я думаю, что проблема может заключаться в вызове optionGSTypes.setArgs(3);
, в соответствии с JavaDoc, он инструктирует commons-cli "Устанавливает число значений аргументов, которые может использовать этот параметр.", то есть вы обязываете commons-cli принимать следующие три аргумента commnadline в качестве аргументов для аргумента "gst".
Кроме того, setValueSeparator(',')
, как представляется, определяет, как обычно используется знак равенства (см. JavaDoc), то есть параметры с форматом, например "key = value", поэтому не то, что вы на самом деле ищете.
В вашем случае я думаю, что самый простой вариант - указать аргумент параметра как простую строку и выполнить синтаксический анализ. Таким образом вы можете полностью контролировать, какие значения допустимы, а также обеспечить лучшее сообщение об ошибке.