Анализатор параметров командной строки для Java

Я пишу оболочку на Java, потому что слишком долго не программировал на Java и многое забыл. Я собирался написать свой собственный, но прямо сейчас я хотел бы получить работающий прототип, поэтому я хотел бы добавить существующий анализатор параметров командной строки.

Требования:

  • Принимает произвольное Stringили String[](т.е. не использует аргументы из командной строки)
  • Принимает аргументы в формате, похожем на getopt(расширенная версия GNU); конкретно:
    • Можно объединить несколько однобуквенных опций (например -a -b -c, -abc)
    • Поддерживает длинные параметры (например --message="Hello!") (хотя он не должен поддерживать длинные параметры с одним тире)
    • Предполагается, что все не опциональные биты в конце являются параметрами, которые должны передаваться нормально (например -abc --long="Hello!" param1 param2, сообщает мне, что параметры param1и param2)
    • --может использоваться для отделения параметров от аргументов (например -ab --custom="hello" -- -file_starting_with_hyphen -another, дает мне параметры/флаги a, bи customс соответствующими значениями и говорит мне, что аргументы -file_starting_with_hyphenи -another)
    • Пробелы могут быть частью аргументов, если они заключены в кавычки.
    • Имя опции, за которой следует значение, анализируется как опция, имеющая это значение (например -h foo, говорит, что есть опция, h, со значением, foo)
  • Полностью кроссплатформенный
  • Мне не нужно указывать, какие параметры я ищу (т.е. я передаю Stringили , String[]и он сообщает мне, какие флаги/параметры были установлены, в отличие от поиска параметров, которые я хочу установить, и предполагая, что остальные являются аргументами )
    • Это означает, что он не использует аннотации, чтобы указать, где хранить значения флагов . По крайней мере, два ответа до сих пор сделали это.
  • Бесплатно (как в пиве)
  • Может легально использоваться в любом проекте (т.е. некоммерческом, не GPL)

Идеально, но не обязательно:

  • Маленький -- один файл
  • Минимальная лицензия на авторские права ( не копилефт - мне нравится не беспокоиться о юридических вопросах, и я ненавижу людей, пытающихся сказать мне, что я не могу использовать свою работу, однако, черт побери, пожалуйста)
  • Использует встроенные интерфейсы ( java.util.Mapв частности, ) для возврата данных. (Это сделано для того, чтобы позже мне было легче написать свою собственную функцию)
  • Открытый исходный код
@a_horse Если я правильно помню, я не использовал его, потому что он требует от меня указать, какие параметры я ищу. Смотрите требования в вопросе.
Я почти уверен, что getopt также требует, чтобы вы указали аргументы, которые вы ищете. И это определенно позволяет объединять односимвольные аргументы, так как же отличить «-top» в качестве длинного аргумента от комбинации -t, -o и -p, не указывая, что допустимо? Я упоминаю об этом, потому что " works like getopt" - ваше второе требование.
@CPerkins «подобно» здесь означает «похоже на», а не «точно так же, как».
Хорошо спасибо. Новый вопрос: мне кажется, что комбинация «не опциональные биты в конце являются параметрами» и «в аргументах разрешены пробелы» неоднозначна. Что, если аргументы заканчиваются на «-n=альфа-бета»? Является ли «бета» частью значения n? Или это параметр?
@CPerkins Я имел в виду, что что-то подобное -n "foo bar baz"будет обрабатываться как флаг nс параметром foo bar baz, а не nс параметром "fooи двумя аргументами, barи baz".
(Прошло некоторое время с тех пор, как я коснулся материала CLI, поэтому я могу получить «параметр» и «аргумент» задом наперед. Что я имею в виду, должно быть ясно.)
Но как насчет -n foo bar baz? С кавычками понятно, что вы хотите. Наверное, я спрашиваю, всегда ли пробел является разделителем.
@CPerkins Там. Если не считать написания полной технической спецификации, это все, на что я способен. Остальное вы можете сделать из того, как обычно работают параметры командной строки.
Понятно. Смотрите ответ.

Ответы (4)

Вы можете проверить FeSimpleArgs

Я считаю, что он выполняет все ваши требования:

Концепция: очень легкий анализатор командной строки. Принимает аргументы в форме String или String[], возвращает экземпляр класса, содержащий аргументы в карте и параметры в списке.

Требования:

  • Принимает произвольную строку или строку[] (т.е. не использует аргументы из командной строки) Да
  • Принимает аргументы в том же формате, что и getopt (расширенная версия GNU); конкретно:
  • Можно объединить несколько однобуквенных опций (например, -a -b -c и -abc) Да
  • Поддерживает длинные параметры (например, --message="Hello!") (хотя не обязательно поддерживать длинные параметры с одним тире) Да
  • Предполагается, что все не опциональные биты в конце являются параметрами, которые должны передаваться нормально (например, -abc --long="Hello!" param1 param2 говорит мне, что это параметры param1 и param2) Да
  • -- можно использовать для отделения параметров от аргументов (например, -ab --custom="hello" -- -file_starting_with_hyphen -another дает мне параметры/флаги a, b и custom с соответствующими значениями и сообщает мне, что аргументы являются -file_starting_with_hyphen и -other) Да
  • Пробелы могут быть частью аргументов, если они заключены в кавычки. Да
  • Имя опции, за которой следует значение, анализируется как опция, имеющая это значение (например, -h foo говорит, что есть опция h со значением foo) Да

  • Полностью кроссплатформенный Да

  • Мне не нужно указывать, какие параметры я ищу (т.е. я передаю ему String или String[], и он сообщает мне, какие флаги/параметры были установлены, в отличие от поиска параметров, которые я хочу установить, и предполагая остальное аргументы) да

что касается использования:

  • Бесплатно (как в пиве) Да - Apache 2.0
  • Можно легально использовать в любом проекте (т.е. некоммерческий, не GPL) Да — Apache 2.0
  • Минимальная лицензия на авторские права (без авторского лева — мне нравится не беспокоиться о юридических вопросах, и я ненавижу людей, пытающихся сказать мне, что я не могу использовать свою работу, однако, черт побери, пожалуйста) Да — Apache 2.0

Публикуется под лицензией Apache 2.0.

Идеально, но не обязательно:

  • Небольшой -- один файл Да (один файл для синтаксического анализатора, один для модульных тестов, не требуется для синтаксического анализа)
  • Использует встроенные интерфейсы (в частности, java.util.Map) для возврата данных. (Это сделано для того, чтобы позже мне было легче написать свою собственную функцию) ** Типа ** (Возвращает класс, содержащий аргументы java.util.Map и список параметров)

ИСПОЛЬЗОВАНИЕ Использование: 1) Создайте экземпляр FeSimpleArgs

FeSimpleArgs parser = new FeSimpleArgs();

2) Используйте его для анализа ваших аргументов:

FeSimpleArgs.Result result = parser.parse ("-def=value1 --GHI=value2 -a -b -c=value3 -n=\"foo bar baz\" -- param1 -param2"); 

3) Изучите свои результаты: из вышеприведенного результат будет состоять из карты, содержащей следующие аргументы и флаги (обратите внимание, что нет никакого реального значения для «аргументов» или «флагов», я просто использую эти термины, чтобы разделить, принимают ли они значения или нет - все они находятся в одной карте).

  • а
  • б
  • д
  • е
  • f со значением = значение1
  • GHI со значением=значение2
  • c со значением=значение3
  • n со значением = foo bar baz (обратите внимание, что кавычки удалены)

И список, содержащий эти параметры (обратите внимание, что начальный дефис сохранен) - param1 - -param2

4) прибыль?

Другие примеры см. в прилагаемых модульных тестах.

Отказ от ответственности: я являюсь автором FeSimpleArgs

Это кажется идеальным, спасибо! Однако есть одна вещь; просто взглянув на код, я вижу несколько вещей, которые не работают - постоянно повторяются compile, Patternкоторые никогда не меняются, tokenize2никогда не используются и так далее. Возможно, вы захотите опубликовать вопрос на CodeReview.SE .
Хорошие наблюдения. Tokenize2 задумывался как попытка использовать другое регулярное выражение. Один из них сейчас не делает того, что мне бы очень хотелось, а именно вытаскивает всю строку в кавычках, даже если перед ней что-то есть. И мне не нравится, когда приходится обрывать кавычки. Возможно, он все еще находится в стадии разработки, но даже в своем несовершенном состоянии он проходит все тесты.

Я успешно использовал args4j в ряде проектов. Он был разработан Kohsuke Kawaguchi , который также разработал Jenkins, был главным разработчиком JAXB и других проектов, поэтому у него очень хорошая родословная.

Я думаю, что я плохо сформулировал это в вопросе, но я ищу что-то, что я могу передать String[]и вернуть (например) с Mapпараметрами, а не что-то, что автоматически анализирует и назначает параметры из аргументов, переданных в jarfile . Кроме того, он должен быть в состоянии сказать мне, какие параметры были переданы с какими аргументами, в отличие от того, чтобы я говорил ему, какие параметры искать.

Примечание. Этот ответ устарел, потому что OP отредактировал вопрос, добавив требование, которое это не выполняет (однако это все равно чертовски полезно знать). Смотрите комментарии ниже. ОП НЕ хочет, чтобы вы отрицали этот ответ.

Классикой для этого в Unix/Linux, еще со времен C, была GetOpt().

У Gnome есть порт Java здесь .

Я искал что-то менее основанное на состоянии (я думаю, это слово? Т.е. одна функция, которая возвращает карту вместо сканирования). Кроме того, требование, которое я забыл указать, заключается в том, что он должен иметь возможность извлекать любые произвольные параметры из строки, а не только те, которые я указываю, поскольку это будет передача аргументов для каждой команды и анализ аргументов для каждое заняло бы слишком много времени. Тем не менее, мне это нравится, хотя бы потому, что я могу просмотреть их код, чтобы увидеть, как они это сделали.
Вам лучше обновить свой вопрос для того требования, которое вы забыли, чтобы люди могли вам помочь. счастливого нарезки! Надеюсь, это немного помогло :-)
Я только что сделал :D и, как я уже сказал, это действительно помогло. Спасибо!
И теперь, когда мой ответ больше не актуален, меня минусуют люди, которые не могут прочитать это полностью. Такова жизнь :-(
О, черт. Прости за это. Возможно, стоит отредактировать, поскольку это было написано до того, как были добавлены несколько требований.
Не беспокойтесь об этом. Я здесь не для очков :-) Если вам понравился ответ Стефана, примите его. Также вполне приемлемо опубликовать свой собственный ответ и принять его. Дело в том, чтобы помочь будущим искателям сделать то же самое.
Проблема со Стефаном заключается в том, что мне нужно что-то, что я мог бы легко добавить, в то время как интерфейс командной строки Apache использует около четырнадцати классов и полдюжины строк кода только для анализа чего-то, что можно легко сделать с помощью одного метода, который принимает a Stringи enum , или Predicate<T>, или что-то.
Ну, пожалуйста, не забудьте опубликовать свой ответ здесь, чтобы помочь другим. Если вы что-то кодируете, подумайте о том, чтобы отправить это в FOSS и опубликовать на GitHub.
У меня нет ответа, вот в чем проблема. Я искал один, однако, и написать свой собственный до сих пор не так уж плохо
ждем - затаив дыхание :-)

пикокли могут представлять интерес. Это единый исходный файл, который побуждает авторов приложений командной строки включать его в качестве исходного кода в качестве более простой альтернативы затенению jar-файлов в uberjar. Он также выполняет все другие требования, изложенные в OP - UPDATE: за исключением требования о том, что параметры не могут быть исправлены во время компиляции :-(.

ОБНОВЛЕНИЕ 2: picocli 3.x предлагает программный API в дополнение к API аннотаций, так что теперь он отвечает всем требованиям. Обратите внимание, что Groovy CliBuilder основан на picocli, начиная с Groovy 2.5. Это именно то, о чем просит OP: динамически добавлять параметры и позиционные параметры в команду.

Недавно в него была добавлена ​​функция автозаполнения.

Еще одна функция, которая может вам понравиться, — это цветная справка по использованию.

Минимальная помощь по использованию с цветами ANSI

Возможности парсера:

  • Annotation API: синтаксический анализ — это одна строка кода в вашем приложении.
  • Programmatic API: все, что возможно с аннотациями, можно сделать программно
  • Все строго типизировано - параметры командной строки, а также позиционные параметры
  • Кластеризованные короткие параметры POSIX ( <command> -xvfInputFileа также <command> -x -v -f InputFile) и длинные параметры GNU
  • Модель арности, допускающая минимальное, максимальное и переменное количество параметров, например, "1..*","3..5"
  • Подкоманды (могут быть вложены на произвольную глубину)
  • Работает с Java 5 и выше

Сообщение справки по использованию легко настроить с помощью аннотаций (без программирования). Например:

Расширенное сообщение справки по использованию( источник )

Я не мог не добавить еще один скриншот, чтобы показать, какие справочные сообщения об использовании возможны. Справка по использованию — это лицо вашего приложения, так что будьте изобретательны и получайте удовольствие!

пикокли демо

Отказ от ответственности: я создал пикокли. Обратная связь или вопросы очень приветствуются.

Я не уверен, что вы прочитали мой вопрос полностью. Пожалуйста, убедитесь, что вы прочитали все требования.
Спасибо за разъяснение вопроса. Должно быть, я пропустил это в своем энтузиазме.
Без проблем. Это кажется отличным вариантом для обычного анализатора командной строки, но если бы я хотел именно этого, я сомневаюсь, что мне пришлось бы задавать вопрос; есть много вариантов там.
Понял. Спасибо за положительный отзыв. Я обновил свой ответ, чтобы подчеркнуть, что это не очень хорошее совпадение. Надеюсь, что это все еще будет полезным ответом для других читателей...
Обратите внимание, что начиная с picocli 3.x, в дополнение к API аннотаций, picocli предлагает программный API. Это соответствует всем требованиям ОП. Ярким примером является Groovy CliBuilder: начиная с Groovy 2.5, CliBuilder реализуется с программным API picocli.