如何在 Scala 中对命令行参数进行不区分大小写的匹配?
How to do a case insensitive match for command line arguments in scala?
我正在开发一个用 Scala 编写的命令行工具,其执行方式为:
sbt "run --customerAccount 1234567"
现在,我希望能够灵活地接受 "--CUSTOMERACCOUNT"
或 --cUsToMerAccount
或 --customerACCOUNT
...你明白了
代码如下所示:
lazy val OptionsParser: OptionParser[Args] = new scopt.OptionParser[Args]("scopt") {
head(
"XML Generator",
"Creates XML for testing"
)
help("help").text(s"Prints this usage message. $envUsage")
opt[String]('c', "customerAccount")
.text("Required: Please provide customer account number as -c 12334 or --customerAccount 12334")
.required()
.action { (cust, args) =>
assert(cust.nonEmpty, "cust is REQUIRED!!")
args.copy(cust = cust)
}
}
我假设 opt[String]('c', "customerAccount")
从命令行执行模式匹配并将与“customerAccount”匹配 - 我如何让它与 "--CUSTOMERACCOUNT"
或 --cUsToMerAccount
或 --customerACCOUNT
? args.copy (cust = cust)
到底是做什么的?
如果问题看起来过于基础,我深表歉意。我对 Scala 非常陌生,之前曾在 Java 和 Python 工作过,所以有时我发现语法也有点难以理解。
您通常会使用如下代码解析参数:
OptionsParser.parse(args, Args())
所以如果你想要 case-insensitivity,可能最简单的方法是用
之类的东西规范化 args
的大小写
val canonicalized = args.map(_.toLowerCase)
OptionsParser.parse(canonicalized, Args())
或者,例如,如果您只想规范化以 --
开头且在 --
:
之前的参数
val canonicalized =
args.foldLeft(false -> List.empty[String]) { (state, arg) =>
val (afterDashes, result) = state
if (afterDashes) true -> (arg :: result) // pass through unchanged
else {
if (arg == "==") true -> (arg :: result) // move to afterDash state & pass through
else {
if (arg.startsWith("--")) false -> (arg.toLowerCase :: result)
else false -> (arg :: result) // pass through unchanged
}
}
}
._2 // Extract the result
.reverse // Reverse it back into the original order (if building up a sequence, your first choice should be to build a list in reversed order and reverse at the end)
OptionsParser.parse(canonicalized, Args())
关于第二个问题,因为 Args
(几乎可以肯定)是一个 case class
,它有一个 copy
方法构造一个新对象(很可能,取决于使用情况) 其字段的不同值。所以
args.copy(cust = cust)
创建一个新的 Args
对象,其中:
- 该对象中
cust
字段的值是该块中 cust
变量的值(这基本上是一种使用命名方法参数的有点聪明的 hack)
- 每个其他字段的值都取自
args
我正在开发一个用 Scala 编写的命令行工具,其执行方式为:
sbt "run --customerAccount 1234567"
现在,我希望能够灵活地接受 "--CUSTOMERACCOUNT"
或 --cUsToMerAccount
或 --customerACCOUNT
...你明白了
代码如下所示:
lazy val OptionsParser: OptionParser[Args] = new scopt.OptionParser[Args]("scopt") {
head(
"XML Generator",
"Creates XML for testing"
)
help("help").text(s"Prints this usage message. $envUsage")
opt[String]('c', "customerAccount")
.text("Required: Please provide customer account number as -c 12334 or --customerAccount 12334")
.required()
.action { (cust, args) =>
assert(cust.nonEmpty, "cust is REQUIRED!!")
args.copy(cust = cust)
}
}
我假设 opt[String]('c', "customerAccount")
从命令行执行模式匹配并将与“customerAccount”匹配 - 我如何让它与 "--CUSTOMERACCOUNT"
或 --cUsToMerAccount
或 --customerACCOUNT
? args.copy (cust = cust)
到底是做什么的?
如果问题看起来过于基础,我深表歉意。我对 Scala 非常陌生,之前曾在 Java 和 Python 工作过,所以有时我发现语法也有点难以理解。
您通常会使用如下代码解析参数:
OptionsParser.parse(args, Args())
所以如果你想要 case-insensitivity,可能最简单的方法是用
之类的东西规范化args
的大小写
val canonicalized = args.map(_.toLowerCase)
OptionsParser.parse(canonicalized, Args())
或者,例如,如果您只想规范化以 --
开头且在 --
:
val canonicalized =
args.foldLeft(false -> List.empty[String]) { (state, arg) =>
val (afterDashes, result) = state
if (afterDashes) true -> (arg :: result) // pass through unchanged
else {
if (arg == "==") true -> (arg :: result) // move to afterDash state & pass through
else {
if (arg.startsWith("--")) false -> (arg.toLowerCase :: result)
else false -> (arg :: result) // pass through unchanged
}
}
}
._2 // Extract the result
.reverse // Reverse it back into the original order (if building up a sequence, your first choice should be to build a list in reversed order and reverse at the end)
OptionsParser.parse(canonicalized, Args())
关于第二个问题,因为 Args
(几乎可以肯定)是一个 case class
,它有一个 copy
方法构造一个新对象(很可能,取决于使用情况) 其字段的不同值。所以
args.copy(cust = cust)
创建一个新的 Args
对象,其中:
- 该对象中
cust
字段的值是该块中cust
变量的值(这基本上是一种使用命名方法参数的有点聪明的 hack) - 每个其他字段的值都取自
args