Best way to parse command-line parameters? [closed

2019-01-20 20:42发布

What's the best way to parse command-line parameters in Scala? I personally prefer something lightweight that does not require external jar.

Related:

26条回答
姐就是有狂的资本
2楼-- · 2019-01-20 21:24

I've just found an extensive command line parsing library in scalac's scala.tools.cmd package.

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

查看更多
孤傲高冷的网名
3楼-- · 2019-01-20 21:28

This is what I cooked. It returns a tuple of a map and a list. List is for input, like input file names. Map is for switches/options.

val args = "--sw1 1 input_1 --sw2 --sw3 2 input_2 --sw4".split(" ")
val (options, inputs) = OptParser.parse(args)

will return

options: Map[Symbol,Any] = Map('sw1 -> 1, 'sw2 -> true, 'sw3 -> 2, 'sw4 -> true)
inputs: List[Symbol] = List('input_1, 'input_2)

Switches can be "--t" which x will be set to true, or "--x 10" which x will be set to "10". Everything else will end up in list.

object OptParser {
  val map: Map[Symbol, Any] = Map()
  val list: List[Symbol] = List()

  def parse(args: Array[String]): (Map[Symbol, Any], List[Symbol]) = _parse(map, list, args.toList)

  private [this] def _parse(map: Map[Symbol, Any], list: List[Symbol], args: List[String]): (Map[Symbol, Any], List[Symbol]) = {
    args match {
      case Nil => (map, list)
      case arg :: value :: tail if (arg.startsWith("--") && !value.startsWith("--")) => _parse(map ++ Map(Symbol(arg.substring(2)) -> value), list, tail)
      case arg :: tail if (arg.startsWith("--")) => _parse(map ++ Map(Symbol(arg.substring(2)) -> true), list, tail)
      case opt :: tail => _parse(map, list :+ Symbol(opt), tail)
    }
  }
}
查看更多
叼着烟拽天下
4楼-- · 2019-01-20 21:29

I realize that the question was asked some time ago, but I thought it might help some people, who are googling around (like me), and hit this page.

Scallop looks quite promising as well.

Features (quote from the linked github page):

  • flag, single-value and multiple value options
  • POSIX-style short option names (-a) with grouping (-abc)
  • GNU-style long option names (--opt)
  • Property arguments (-Dkey=value, -D key1=value key2=value)
  • Non-string types of options and properties values (with extendable converters)
  • Powerful matching on trailing args
  • Subcommands

And some example code (also from that Github page):

import org.rogach.scallop._;

object Conf extends ScallopConf(List("-c","3","-E","fruit=apple","7.2")) {
  // all options that are applicable to builder (like description, default, etc) 
  // are applicable here as well
  val count:ScallopOption[Int] = opt[Int]("count", descr = "count the trees", required = true)
                .map(1+) // also here work all standard Option methods -
                         // evaluation is deferred to after option construction
  val properties = props[String]('E')
  // types (:ScallopOption[Double]) can be omitted, here just for clarity
  val size:ScallopOption[Double] = trailArg[Double](required = false)
}


// that's it. Completely type-safe and convenient.
Conf.count() should equal (4)
Conf.properties("fruit") should equal (Some("apple"))
Conf.size.get should equal (Some(7.2))
// passing into other functions
def someInternalFunc(conf:Conf.type) {
  conf.count() should equal (4)
}
someInternalFunc(Conf)
查看更多
Evening l夕情丶
5楼-- · 2019-01-20 21:29

I'm going to pile on. I solved this with a simple line of code. My command line arguments look like this:

input--hdfs:/path/to/myData/part-00199.avro output--hdfs:/path/toWrite/Data fileFormat--avro option1--5

This creates an array via Scala's native command line functionality (from either App or a main method):

Array("input--hdfs:/path/to/myData/part-00199.avro", "output--hdfs:/path/toWrite/Data","fileFormat--avro","option1--5")

I can then use this line to parse out the default args array:

val nArgs = args.map(x=>x.split("--")).map(y=>(y(0),y(1))).toMap

Which creates a map with names associated with the command line values:

Map(input -> hdfs:/path/to/myData/part-00199.avro, output -> hdfs:/path/toWrite/Data, fileFormat -> avro, option1 -> 5)

I can then access the values of named parameters in my code and the order they appear on the command line is no longer relevant. I realize this is fairly simple and doesn't have all the advanced functionality mentioned above but seems to be sufficient in most cases, only needs one line of code, and doesn't involve external dependencies.

查看更多
smile是对你的礼貌
6楼-- · 2019-01-20 21:30

Here's a scala command line parser that is easy to use. It automatically formats help text, and it converts switch arguments to your desired type. Both short POSIX, and long GNU style switches are supported. Supports switches with required arguments, optional arguments, and multiple value arguments. You can even specify the finite list of acceptable values for a particular switch. Long switch names can be abbreviated on the command line for convenience. Similar to the option parser in the Ruby standard library.

查看更多
一纸荒年 Trace。
7楼-- · 2019-01-20 21:31

scala-optparse-applicative

I think scala-optparse-applicative is the most functional command line parser library in Scala.

https://github.com/bmjames/scala-optparse-applicative

查看更多
登录 后发表回答