В большинстве случаев вам не нужен внешний парсер. Сопоставление с образцом в Scala позволяет использовать аргументы в функциональном стиле. Например:
object MmlAlnApp {
val usage = """
Usage: mmlaln [--min-size num] [--max-size num] filename
"""
def main(args: Array[String]) {
if (args.length == 0) println(usage)
val arglist = args.toList
type OptionMap = Map[Symbol, Any]
def nextOption(map : OptionMap, list: List[String]) : OptionMap = {
def isSwitch(s : String) = (s(0) == '-')
list match {
case Nil => map
case "--max-size" :: value :: tail =>
nextOption(map ++ Map('maxsize -> value.toInt), tail)
case "--min-size" :: value :: tail =>
nextOption(map ++ Map('minsize -> value.toInt), tail)
case string :: opt2 :: tail if isSwitch(opt2) =>
nextOption(map ++ Map('infile -> string), list.tail)
case string :: Nil => nextOption(map ++ Map('infile -> string), list.tail)
case option :: tail => println("Unknown option "+option)
exit(1)
}
}
val options = nextOption(Map(),arglist)
println(options)
}
}
напечатает, например:
Map('infile -> test/data/paml-aln1.phy, 'maxsize -> 4, 'minsize -> 2)
Эта версия занимает всего один инфиль. Легко улучшить (с помощью списка).
Также обратите внимание, что этот подход позволяет объединять несколько аргументов командной строки - даже более двух!
nextOption
не хорошее название для функции. Это функция, которая возвращает карту - тот факт, что она является рекурсивной, является деталью реализации. Это похоже на написаниеmax
функции для коллекции и вызов ееnextMax
просто потому, что вы написали ее с явной рекурсией. Почему бы просто не позвонитьoptionMap
?listToOptionMap(lst:List[String])
с помощью функции,nextOption
определенной в ней, с заключительной строчкойreturn nextOption(Map(), lst)
. Тем не менее, я должен признаться, что я сделал гораздо больше вопиющих ярлыков в свое время, чем тот, что в этом ответе.exit(1)
может потребоватьсяsys.exit(1)
file
параметрами:case string :: tail => { if (isSwitch(string)) { println("Unknown option: " + string) sys.exit(1) } else nextOption(map ++ Map('files -> (string :: map('files).asInstanceOf[List[String]])), tail)
. Карта также нуждается в значении по умолчаниюNil
, то естьval options = nextOption(Map() withDefaultValue Nil, args.toList)
. Что мне не нравится, так это необходимость прибегать к помощиasInstanceOf
из-за того, чтоOptionMap
значения имеют типAny
. Есть ли лучшее решение?scopt / scopt
Выше генерируется следующий текст использования:
Это то, что я сейчас использую. Чистое использование без большого количества багажа. (Отказ от ответственности: я сейчас поддерживаю этот проект)
источник
Я понимаю, что вопрос был задан некоторое время назад, но я подумал, что это может помочь некоторым людям, которые ищут в Google (например, я), и попасть на эту страницу.
Гребешок выглядит довольно многообещающе.
Особенности (цитата из связанной страницы GitHub):
И пример кода (также с этой страницы Github):
источник
(x, c) => c.copy(xyz = x)
в областиМне нравится скользить по аргументам для относительно простых конфигураций.
источник
args.sliding(2, 2)
?var port = 0
?Scala Toolkit интерфейса командной строки (CLIST)
вот мой тоже! (немного поздно в игре, хотя)
https://github.com/backuity/clist
В отличие от
scopt
этого полностью изменчиво ... но подождите! Это дает нам довольно хороший синтаксис:И простой способ запустить его:
Конечно, вы можете сделать намного больше (много команд, много опций конфигурации, ...) и не зависеть.
Я закончу с некоторой отличительной особенностью, использованием по умолчанию (довольно часто игнорируемым для нескольких команд):
источник
Password
,Hex
...), то вы можете использовать это.Это в значительной степени бесстыдный клон моего ответа на вопрос Java по той же теме . Оказывается, что JewelCLI является Scala-дружественным в том смысле, что он не требует методов стиля JavaBean для получения автоматического именования аргументов.
JewelCLI - это Scala-дружественная библиотека Java для анализа командной строки, которая дает чистый код . Он использует прокси-интерфейсы, сконфигурированные с аннотациями, для динамического построения безопасного с точки зрения типов API для параметров командной строки.
Пример интерфейса параметров
Person.scala
:Пример использования интерфейса параметров
Hello.scala
:Сохраните копии файлов выше в одном каталоге и загрузите JAR JewelCLI 0.6 в этот каталог.
Скомпилируйте и запустите пример в Bash для Linux / Mac OS X / etc:
Скомпилируйте и запустите пример в командной строке Windows:
Запуск примера должен привести к следующему выводу:
источник
Как разобрать параметры без внешней зависимости. Отличный вопрос! Вы можете быть заинтересованы в пикокли .
Picocli специально разработан для решения проблемы, заданной в вопросе: это среда синтаксического анализа командной строки в одном файле, поэтому вы можете включить ее в исходную форму . Это позволяет пользователям запускать приложения на основе picocli, не требуя picocli в качестве внешней зависимости .
Он работает путем аннотирования полей, поэтому вы пишете очень мало кода. Краткое резюме:
<command> -xvfInputFile
так же, как<command> -x -v -f InputFile
)"1..*"
,"3..5"
Сообщение об использовании легко настроить с помощью аннотаций (без программирования). Например:
( источник )
Я не мог удержаться от добавления еще одного скриншота, чтобы показать, какие виды справочных сообщений об использовании возможны. Справка по использованию - это лицо вашего приложения, так что будьте изобретательны и получайте удовольствие!
Отказ от ответственности: я создал picocli. Отзывы или вопросы очень приветствуются. Он написан на Java, но дайте мне знать, если есть какие-либо проблемы с его использованием в Scala, и я постараюсь решить ее.
источник
Я из мира Java, мне нравится args4j, потому что его простая спецификация более читабельна (благодаря аннотациям) и производит красиво отформатированный вывод.
Вот мой пример фрагмента:
Технические характеристики
Анализировать
На недопустимых аргументах
источник
Скала-optparse-аппликативны
Я думаю, что scala-optparse-Applicative является самой функциональной библиотекой парсера командной строки в Scala.
https://github.com/bmjames/scala-optparse-applicative
источник
examples
в тестовом кодеТакже есть JCommander (отказ от ответственности: я его создал):
источник
Мне понравился метод joslinm, использующий слайд (), но не изменяемые переменные;) Так что вот неизменный путь к этому подходу:
источник
Я только что нашел обширную библиотеку синтаксического анализа командной строки в пакете scac.tools.cmd.
См. Http://www.assembla.com/code/scala-eclipse-toolchain/git/nodes/src/compiler/scala/tools/cmd?rev=f59940622e32384b1e08939effd24e924a8ba8db
источник
Я попытался обобщить решение @ pjotrp, взяв список требуемых позиционных символов клавиш, карту флага -> символ ключа и параметры по умолчанию:
источник
-f|--flags
. Взгляните на gist.github.com/DavidGamba/b3287d40b019e498982c и не стесняйтесь обновлять ответ, если вам это нравится. Я, вероятно, сделаю каждую карту и опцию, чтобы вы могли передавать только то, что вам нужно, с именованными аргументами.Я основал свой подход на верхнем ответе (из dave4420) и попытался улучшить его, сделав его более универсальным.
Он возвращает один
Map[String,String]
из всех параметров командной строки. Вы можете запросить его для конкретных параметров, которые вы хотите (например, используя.contains
) или преобразовать значения в типы, которые вы хотите (например, используяtoInt
).Пример:
дает:
источник
другая библиотека: scarg
источник
Вот анализатор командной строки Scala, который прост в использовании. Он автоматически форматирует текст справки и преобразует аргументы переключателя в нужный вам тип. Поддерживаются как короткие POSIX, так и длинные переключатели в стиле GNU. Поддерживает переключатели с необходимыми аргументами, необязательными аргументами и аргументами с несколькими значениями. Вы даже можете указать конечный список допустимых значений для конкретного переключателя. Длинные имена переключателей могут быть сокращены в командной строке для удобства. Аналогично параметру parser в стандартной библиотеке Ruby.
источник
Я никогда не любил рубиновые парсеры опций. Большинство разработчиков, которые их использовали, никогда не пишут правильную справочную страницу для своих сценариев и в итоге получают длинные страницы, не организованные должным образом из-за их синтаксического анализатора.
Я всегда предпочитал способ работы Perl с помощью Perl's Getopt :: Long .
Я работаю над его реализацией. Ранний API выглядит примерно так:
Так зовем
script
вот так:Будет печатать:
И вернуться:
Проект размещен в github scala-getoptions .
источник
Я только что создал мое простое перечисление
Я понимаю, что у решения есть два основных недостатка, которые могут вас отвлечь: оно устраняет свободу (то есть зависимость от других библиотек, которую вы так цените) и избыточность (принцип DRY, вы вводите имя опции только один раз, как программа Scala). Переменный и устранить его во второй раз набранный как текст командной строки).
источник
Я бы предложил использовать http://docopt.org/ . Есть scala-порт, но реализация Java https://github.com/docopt/docopt.java работает просто отлично и, кажется, лучше поддерживается. Вот пример:
источник
Это то, что я приготовил. Возвращает кортеж карты и список. Список для ввода, как имена входных файлов. Карта для переключателей / опций.
вернется
Переключатели могут быть "--t", для которых x будет установлено в "истина", или "--x 10", для которых x будет установлено в "10". Все остальное попадет в список.
источник
Мне нравится чистый вид этого кода ... почерпнутый из обсуждения здесь: http://www.scala-lang.org/old/node/4380
источник
Поскольку все выкладывают свое собственное решение, здесь мое, потому что я хотел написать что-то более простое для пользователя: https://gist.github.com/gwenzek/78355526e476e08bb34d
Суть содержит файл кода, плюс тестовый файл и короткий пример, скопированный здесь:
Там нет причудливых вариантов, чтобы заставить переменную находиться в определенных границах, потому что я не чувствую, что синтаксический анализатор - лучшее место для этого.
Примечание: вы можете иметь столько псевдонимов, сколько хотите для данной переменной.
источник
Я собираюсь нагромождать. Я решил это с помощью простой строки кода. Мои аргументы командной строки выглядят так:
Это создает массив с помощью встроенной функции командной строки Scala (из приложения или основного метода):
Затем я могу использовать эту строку для анализа массива args по умолчанию:
Который создает карту с именами, связанными со значениями командной строки:
Затем я могу получить доступ к значениям именованных параметров в моем коде, и порядок их появления в командной строке больше не имеет значения. Я понимаю, что это довольно просто и не имеет всей расширенной функциональности, упомянутой выше, но кажется достаточной в большинстве случаев, требует только одну строку кода и не включает внешних зависимостей.
источник
Вот мой 1-лайнер
Он отбрасывает 3 обязательных аргумента и выдает опции. Целые числа указываются как пресловутая
-Xmx<size>
опция java вместе с префиксом. Вы можете анализировать двоичные и целые числа так же просто, какНе нужно ничего импортировать.
источник
Бедняжка быстро и грязно однослойно разбирает пары ключ-значение:
источник
freecli
Это сгенерирует следующее использование:
использование
источник