如何在 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