Подтвердить что ты не робот

Почему определенные параметры 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();

результирующие, проанализированные значения обнаруживаются некорректно как:

  • "категория"
  • "- GSD"
  • "4"

Подсказка: я использовал отладчик, чтобы проверить неверный результат процесса синтаксического анализа, проверив поле values в org.apache.commons.cli.Option с помощью возвращаемой переменной commands.

Мое ожидание будет состоять в том, что внутреннее изменение анализатора должно не давать разные результаты, так как это нарушает существующий код. Кто-нибудь сталкивался с тем же поведением с Apache Commons-CLI при переключении на DefaultParser и несколькими значениями параметров и пользовательскими разделителями?

Есть ли разница в конструкции/использовании DefaultParser, которую я мог бы контролировать?

4b9b3361

Ответ 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", поэтому не то, что вы на самом деле ищете.

В вашем случае я думаю, что самый простой вариант - указать аргумент параметра как простую строку и выполнить синтаксический анализ. Таким образом вы можете полностью контролировать, какие значения допустимы, а также обеспечить лучшее сообщение об ошибке.