String Scala运行时字符串插值/格式化

String Scala运行时字符串插值/格式化,string,scala,String,Scala,有没有标准的库工具可以在运行时进行字符串插值/格式化?我希望格式化的行为与基于宏的s“scala${implementation}完全相同,只是我的字符串格式是在运行时从配置文件加载的 val format = config.getString("my.key") val stringContext = parseFormat(format) val res = stringContext.f("arg1", "arg2") 使用parseFormat返回一个 我想象,在最坏的情况下,我可以拆

有没有标准的库工具可以在运行时进行字符串插值/格式化?我希望格式化的行为与基于宏的
s“scala${implementation}
完全相同,只是我的字符串格式是在运行时从配置文件加载的

val format = config.getString("my.key")
val stringContext = parseFormat(format)
val res = stringContext.f("arg1", "arg2")
使用
parseFormat
返回一个

我想象,在最坏的情况下,我可以拆分“{}”序列上的字符串,并使用这些部分来构造StringContext

// untested
def parseFormat(format: String): StringContext =
  new StringContext("""{}""".r.split(format): _*)

有没有一个明显的解决方案是我没有的,或者上面的黑客会这样做?

A.从Scala 2.10.3开始,你不能使用
StringContext.f
,除非你知道编译时的参数数量,因为
.f
方法是一个宏


B.使用
String.format
,就像在Java的好时光一样。

没有愚蠢的问题。只有周日上午

首先

事实证明,斯普利特并没有完全破解它

scala> StringContext("Count to {}" split "\\{}" : _*) s 42
java.lang.IllegalArgumentException: wrong number of arguments (1) for interpolated string with 1 parts
  at scala.StringContext.checkLengths(StringContext.scala:65)
  at scala.StringContext.standardInterpolator(StringContext.scala:121)
  at scala.StringContext.s(StringContext.scala:94)
  ... 33 elided
如此给定

scala> val r = "\\{}".r
r: scala.util.matching.Regex = \{}

scala> def parts(s: String) = r split s
parts: (s: String)Array[String]
也许吧

所以

嘿,等等

scala> def f(parts: Seq[String], args: Any*) = (parts.zipAll(args, "", "") map (p => p._1 + p._2)).mkString
f: (parts: Seq[String], args: Any*)String

scala> f(parts("Hello, {}. Today is {}."), "Bob", "Tuesday")
res9: String = Hello, Bob. Today is Tuesday.

scala>def(部分:Seq[String],args:Any*)=(对于(i“”)+args.applyOrElse(i,(:Int)=>)).mkString
f:(parts:Seq[String],args:Any*)字符串

scala>def(parts:Seq[String],args:Any*)={val sb=new StringBuilder;for(parts(“你好,{}。今天是{}.{}”),“Bob”,“星期二”,“再见!”)
res16:String=你好,鲍勃。今天是星期二。再见!

我有一个类似的要求,我从一个配置文件加载一个
Seq[String]
,该文件将成为一个要执行的命令(使用
scala.sys.process
)。为了简化格式并忽略任何潜在的转义问题,我还将变量名设置为一个可配置选项

配置如下所示:

command = ["""C:\Program Files (x86)\PuTTY\pscp.exe""", "-P", "2222", "-i",
          ".vagrant/machines/default/virtualbox/private_key", "$source", "~/$target"]
source = "$source"
target = "$target"
我找不到一个好的(或有效的)方法来使用
StringContext
“string.format
,所以我使用了自己的格式,它与
StringContext
非常相似,但是单个变量可以在任何顺序和任何项目中出现零次或多次

基本思想是创建一个函数,该函数接受变量值,然后要么接受字符串的一部分(例如
“~/”
),要么重复接受变量值(例如
“test.conf”
),以建立结果(例如
“~/test.conf”
).这个函数只创建一次,这是所有复杂的地方,在替换时它非常简单(希望很快,尽管我没有做过任何性能测试,也没有做过很多测试)


对于那些可能想知道我为什么这么做的人来说,这是为了使用ansible(不支持Windows控制机器)跨平台运行自动化测试用于设置。这允许我将文件复制到目标计算机,并在本地运行ansible。

我想您希望从String#format(,java.lang.Object…)的功能中获得更多的
格式.你能告诉我你需要什么吗?我想那就行了。有没有办法结束我自己的问题,因为我太愚蠢了?我不介意你把它删除,尽管它可能会给那些同样面临类似问题并且已经忘记字符串格式的人一个指导。:)
scala> def f(parts: Seq[String], args: Any*) = (parts zip args map (p => p._1 + p._2)).mkString
f: (parts: Seq[String], args: Any*)String
scala> val count = parts("Count to {}")
count: Array[String] = Array("Count to ")

scala> f(count, 42)
res7: String = Count to 42

scala> f(parts("Hello, {}. Today is {}."), "Bob", "Tuesday")
res8: String = Hello, Bob. Today is Tuesday
scala> def f(parts: Seq[String], args: Any*) = (parts.zipAll(args, "", "") map (p => p._1 + p._2)).mkString
f: (parts: Seq[String], args: Any*)String

scala> f(parts("Hello, {}. Today is {}."), "Bob", "Tuesday")
res9: String = Hello, Bob. Today is Tuesday.
scala> def f(parts: Seq[String], args: Any*) = (for (i <- 0 until (parts.size max args.size)) yield (parts.applyOrElse(i, (_: Int) => "") + args.applyOrElse(i, (_: Int) => ""))).mkString
f: (parts: Seq[String], args: Any*)String
scala> def f(parts: Seq[String], args: Any*) = { val sb = new StringBuilder ; for (i <- 0 until (parts.size max args.size) ; ss <- List(parts, args)) { sb append ss.applyOrElse(i, (_: Int) => "") } ; sb.toString }
f: (parts: Seq[String], args: Any*)String

scala> f(parts("Hello, {}. Today is {}. {}"), "Bob", "Tuesday", "Bye!")
res16: String = Hello, Bob. Today is Tuesday. Bye!
command = ["""C:\Program Files (x86)\PuTTY\pscp.exe""", "-P", "2222", "-i",
          ".vagrant/machines/default/virtualbox/private_key", "$source", "~/$target"]
source = "$source"
target = "$target"