Лучший способ проанализировать параметры командной строки? [закрытый]

232
задан axreldable 18 February 2019 в 20:01
поделиться

4 ответа

scopt / scopt

val parser = new scopt.OptionParser[Config]("scopt") {
  head("scopt", "3.x")

  opt[Int]('f', "foo") action { (x, c) =>
    c.copy(foo = x) } text("foo is an integer property")

  opt[File]('o', "out") required() valueName("<file>") action { (x, c) =>
    c.copy(out = x) } text("out is a required file property")

  opt[(String, Int)]("max") action { case ((k, v), c) =>
    c.copy(libName = k, maxCount = v) } validate { x =>
    if (x._2 > 0) success
    else failure("Value <max> must be >0") 
  } keyValueName("<libname>", "<max>") text("maximum count for <libname>")

  opt[Unit]("verbose") action { (_, c) =>
    c.copy(verbose = true) } text("verbose is a flag")

  note("some notes.\n")

  help("help") text("prints this usage text")

  arg[File]("<file>...") unbounded() optional() action { (x, c) =>
    c.copy(files = c.files :+ x) } text("optional unbounded args")

  cmd("update") action { (_, c) =>
    c.copy(mode = "update") } text("update is a command.") children(
    opt[Unit]("not-keepalive") abbr("nk") action { (_, c) =>
      c.copy(keepalive = false) } text("disable keepalive"),
    opt[Boolean]("xyz") action { (x, c) =>
      c.copy(xyz = x) } text("xyz is a boolean property")
  )
}
// parser.parse returns Option[C]
parser.parse(args, Config()) map { config =>
  // do stuff
} getOrElse {
  // arguments are bad, usage message will have been displayed
}

Приведенное выше генерирует следующий текст использования:

scopt 3.x
Usage: scopt [update] [options] [<file>...]

  -f <value> | --foo <value>
        foo is an integer property
  -o <file> | --out <file>
        out is a required file property
  --max:<libname>=<max>
        maximum count for <libname>
  --verbose
        verbose is a flag
some notes.

  --help
        prints this usage text
  <file>...
        optional unbounded args

Command: update
update is a command.

  -nk | --not-keepalive
        disable keepalive    
  --xyz <value>
        xyz is a boolean property

Это то, что я использую в настоящее время. Чистое использование без лишнего багажа. (Отказ от ответственности: сейчас я поддерживаю этот проект)

194
ответ дан 23 November 2019 в 03:34
поделиться

В большинстве случаев внешний синтаксический анализатор не требуется. Сопоставление с образцом в 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)

Эта версия принимает только один файл. Легко улучшить (с помощью списка).

Отметим также, что этот подход позволяет объединять несколько аргументов командной строки - даже более двух!

222
ответ дан 23 November 2019 в 03:34
поделиться

Это в значительной степени бесстыдный клон моего ответа на вопрос Java той же темы . Оказывается, JewelCLI дружественна к Scala в том смысле, что не требует методов в стиле JavaBean для автоматического именования аргументов.

JewelCLI - это дружественная к Scala библиотека Java для синтаксического анализа командной строки, которая дает чистый код . Он использует прокси-интерфейсы, настроенные с аннотациями, для динамического создания типобезопасного API для ваших параметров командной строки.

Пример интерфейса параметров Person.scala :

import uk.co.flamingpenguin.jewel.cli.Option

trait Person {
  @Option def name: String
  @Option def times: Int
}

Пример использования интерфейса параметров Hello.scala :

import uk.co.flamingpenguin.jewel.cli.CliFactory.parseArguments
import uk.co.flamingpenguin.jewel.cli.ArgumentValidationException

object Hello {
  def main(args: Array[String]) {
    try {
      val person = parseArguments(classOf[Person], args:_*)
      for (i <- 1 to (person times))
        println("Hello " + (person name))
    } catch {
      case e: ArgumentValidationException => println(e getMessage)
    }
  }
}

Сохранение копий файлов выше в один каталог и также загрузите в этот каталог JewelCLI 0.6 JAR .

Скомпилируйте и запустите пример в Bash в Linux / Mac OS X и т. Д .:

scalac -cp jewelcli-0.6.jar:. Person.scala Hello.scala
scala -cp jewelcli-0.6.jar:. Hello --name="John Doe" --times=3

Скомпилируйте и запустите пример в командной строке Windows:

scalac -cp jewelcli-0.6.jar;. Person.scala Hello.scala
scala -cp jewelcli-0.6.jar;. Hello --name="John Doe" --times=3

Выполнение примера должно дать следующий результат:

Hello John Doe
Hello John Doe
Hello John Doe
13
ответ дан 23 November 2019 в 03:34
поделиться

Я только что нашел обширную библиотеку разбора командной строки в пакете scalac scala.tools.cmd.

См. http://www.assembla.com/code/scala-eclipse-toolchain/git/nodes/src/compiler/scala/tools/cmd?rev=f59940622e32384b1e08939effd24e924a8ba8db

3
ответ дан 23 November 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: