在Scala中解析命令行参数的最佳方法是什么? 我个人更喜欢一些不需要外部罐子的轻量级的东西。
相关:
我如何解析Java中的命令行参数? c++有哪些参数解析器库? 在c#中解析命令行参数的最佳方法
在Scala中解析命令行参数的最佳方法是什么? 我个人更喜欢一些不需要外部罐子的轻量级的东西。
相关:
我如何解析Java中的命令行参数? c++有哪些参数解析器库? 在c#中解析命令行参数的最佳方法
当前回答
scala-optparse-applicative
我认为Scala -optparse-applicative是Scala中功能最强大的命令行解析器库。
https://github.com/bmjames/scala-optparse-applicative
其他回答
因为每个人都发布了自己的解决方案,这里是我的,因为我想为用户写一些更简单的东西:https://gist.github.com/gwenzek/78355526e476e08bb34d
要点包含一个代码文件,一个测试文件和一个简短的示例复制在这里:
import ***.ArgsOps._
object Example {
val parser = ArgsOpsParser("--someInt|-i" -> 4, "--someFlag|-f", "--someWord" -> "hello")
def main(args: Array[String]){
val argsOps = parser <<| args
val someInt : Int = argsOps("--someInt")
val someFlag : Boolean = argsOps("--someFlag")
val someWord : String = argsOps("--someWord")
val otherArgs = argsOps.args
foo(someWord, someInt, someFlag)
}
}
没有什么特别的选项可以强制变量在某些边界内,因为我觉得解析器不是这样做的最佳场所。
注意:对于一个给定的变量,你可以有任意多的别名。
命令行接口Scala Toolkit (CLIST)
这也是我的!(虽然有点晚了)
https://github.com/backuity/clist
与scopt相反,它是完全可变的…但是等等!这给了我们一个很好的语法:
class Cat extends Command(description = "concatenate files and print on the standard output") {
// type-safety: members are typed! so showAll is a Boolean
var showAll = opt[Boolean](abbrev = "A", description = "equivalent to -vET")
var numberNonblank = opt[Boolean](abbrev = "b", description = "number nonempty output lines, overrides -n")
// files is a Seq[File]
var files = args[Seq[File]](description = "files to concat")
}
还有一个简单的运行方法:
Cli.parse(args).withCommand(new Cat) { case cat =>
println(cat.files)
}
当然,您可以做更多的事情(多命令,许多配置选项,……),并且没有依赖性。
我将以一种独特的特性来结束,默认用法(对于多个命令经常被忽略):
对于相对简单的配置,我喜欢滑动参数。
var name = ""
var port = 0
var ip = ""
args.sliding(2, 2).toList.collect {
case Array("--ip", argIP: String) => ip = argIP
case Array("--port", argPort: String) => port = argPort.toInt
case Array("--name", argName: String) => name = argName
}
对于大多数情况,您不需要外部解析器。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)
这个版本只需要一个文件。很容易改进(通过使用列表)。
还要注意,这种方法允许连接多个命令行参数——甚至超过两个!
scala-optparse-applicative
我认为Scala -optparse-applicative是Scala中功能最强大的命令行解析器库。
https://github.com/bmjames/scala-optparse-applicative