String 具有命名值的字符串格式

String 具有命名值的字符串格式,string,scala,String,Scala,我正在寻找一种惯用的scala方法来格式化带有命名参数的字符串。我知道String方法格式,但它不允许指定命名参数,只有位置参数可用 简单的例子: val bob = "Bob" val alice = "Alice" val message = "${b} < ${a} and ${a} > ${b}" message.format(a = alice, b = bob) val bob=“bob” val alice=“alice” val message=“${b}${b}”

我正在寻找一种惯用的scala方法来格式化带有命名参数的字符串。我知道String方法格式,但它不允许指定命名参数,只有位置参数可用

简单的例子:

val bob = "Bob"
val alice = "Alice"
val message = "${b} < ${a} and ${a} > ${b}"
message.format(a = alice, b = bob)
val bob=“bob”
val alice=“alice”
val message=“${b}<${a}和${a}>${b}”
message.format(a=alice,b=bob)

将消息定义为单独的值是至关重要的,因为我希望从资源文件加载它,而不是直接在代码中指定。使用名为字符串插值的新scala功能,可以回答许多类似的问题。但这并不能解决我的问题:我不能让编译器完成所有的工作,因为资源文件是在运行时加载的。

一种方法可能是有一个替换列表(不限制变量的数量),然后执行以下操作:

def substituteVar(s:String,subs:Seq[(String,String)]):String=
  subs.foldLeft(s)((soFar,item) => soFar replaceAll("\\$\\{"+item._1+"}", item._2))

substituteVar(message,Seq(("a",alice),("b",bob)))
res12: String = Bob < Alice and Alice > Bob
def substituteVar(s:String,subs:Seq[(String,String)]):String=
子文件夹((soFar,项目)=>soFar replaceAll(\\$\\{item.\U 1+“}”,项目.\U 2))
替代变量(消息,序号((“a”,alice),(“b”,bob)))
res12:String=BobBob

也可以扩展

一种方法可能是有一个替换列表(不限制变量的数量),然后使用如下内容:

def substituteVar(s:String,subs:Seq[(String,String)]):String=
  subs.foldLeft(s)((soFar,item) => soFar replaceAll("\\$\\{"+item._1+"}", item._2))

substituteVar(message,Seq(("a",alice),("b",bob)))
res12: String = Bob < Alice and Alice > Bob
def substituteVar(s:String,subs:Seq[(String,String)]):String=
子文件夹((soFar,项目)=>soFar replaceAll(\\$\\{item.\U 1+“}”,项目.\U 2))
替代变量(消息,序号((“a”,alice),(“b”,bob)))
res12:String=BobBob

也可以扩展

我不知道是否可以使用编译器使用的相同解析器

但是
Regex
可以处理您给出的示例

val values = Map("a" -> "Alice", "b" -> "Bob")
val message = "${b} < ${a} and ${a} > ${b}"

def escapeReplacement(s: String): String = 
  s.replace("\\", "\\\\").replace("$", "\\$")

"\\$\\{([^\\}]*)\\}".r.replaceAllIn(message,
  m => escapeReplacement(values(m.group(1))))
val values=Map(“a”->“Alice”、“b”->“Bob”)
val message=“${b}<${a}和${a}>${b}”
def转义替换(s:字符串):字符串=
s、 替换(“\\”、“\\\”)。替换(“$”、“\\$”)
“\\$\{([^\\}]*)\\}”.r.replaceAllIn(消息,
m=>逃逸置换(值(m.group(1)))

我不知道是否可以使用编译器使用的相同解析器

但是
Regex
可以处理您给出的示例

val values = Map("a" -> "Alice", "b" -> "Bob")
val message = "${b} < ${a} and ${a} > ${b}"

def escapeReplacement(s: String): String = 
  s.replace("\\", "\\\\").replace("$", "\\$")

"\\$\\{([^\\}]*)\\}".r.replaceAllIn(message,
  m => escapeReplacement(values(m.group(1))))
val values=Map(“a”->“Alice”、“b”->“Bob”)
val message=“${b}<${a}和${a}>${b}”
def转义替换(s:字符串):字符串=
s、 替换(“\\”、“\\\”)。替换(“$”、“\\$”)
“\\$\{([^\\}]*)\\}”.r.replaceAllIn(消息,
m=>逃逸置换(值(m.group(1)))
不清楚“位置参数”是指通常意义上的还是
格式化程序使用的“参数索引”意义上的

scala> val bob = "Bob"
bob: String = Bob

scala> val alice = "Alice"
alice: String = Alice

scala> val message = "%2$s likes %1$s and %1$s likes %2$s" format (bob, alice)
message: String = Alice likes Bob and Bob likes Alice
你想:

scala> def f(a: String, b: String) = s"$b likes $a and $a likes $b"
f: (a: String, b: String)String

scala> f(b = bob, a = alice)
res2: String = Bob likes Alice and Alice likes Bob
可以使用反射工具箱或脚本引擎编译插值

scala> import scala.tools.reflect._
import scala.tools.reflect._

scala> val tb = reflect.runtime.currentMirror.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@162b3d47

scala> val defs = s"""val a = "$alice" ; val b = "$bob""""
defs: String = val a = "Alice" ; val b = "Bob"

scala> val message = "${b} < ${a} and ${a} > ${b}"
message: String = ${b} < ${a} and ${a} > ${b}

scala> val msg = s"""s"$message""""
msg: String = s"${b} < ${a} and ${a} > ${b}"

scala> tb eval (tb parse s"$defs ; $msg")
res3: Any = Bob < Alice and Alice > Bob
scala>导入scala.tools.reflect_
导入scala.tools.reflect_
scala>val tb=reflect.runtime.currentMirror.mkToolBox()
tb:scala.tools.reflect.ToolBox[reflect.runtime.universe.type]=scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@162b3d47
scala>val defs=s“val a=“$alice”;val b=“$bob”
defs:String=val a=“Alice”;val b=“鲍勃”
scala>val message=“${b}<${a}和${a}>${b}”
消息:String=${b}<${a}和${a}>${b}
scala>val msg=s“s”$message”
msg:String=s“${b}<${a}和${a}>${b}”
scala>tb eval(tb解析s“$defs;$msg”)
res3:Any=BobBob

scala>def(a:String,b:String)=tb eval(tb parse s”““val a=“$a”val b=“$b”s“$message”“”“)
f:(a:字符串,b:字符串)任何
scala>f(a=alice,b=bob)
res4:Any=BobBob
有点太多了

但请考虑:

不清楚“位置参数”是指通常意义上的还是
格式化程序使用的“参数索引”意义上的

scala> val bob = "Bob"
bob: String = Bob

scala> val alice = "Alice"
alice: String = Alice

scala> val message = "%2$s likes %1$s and %1$s likes %2$s" format (bob, alice)
message: String = Alice likes Bob and Bob likes Alice
你想:

scala> def f(a: String, b: String) = s"$b likes $a and $a likes $b"
f: (a: String, b: String)String

scala> f(b = bob, a = alice)
res2: String = Bob likes Alice and Alice likes Bob
可以使用反射工具箱或脚本引擎编译插值

scala> import scala.tools.reflect._
import scala.tools.reflect._

scala> val tb = reflect.runtime.currentMirror.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@162b3d47

scala> val defs = s"""val a = "$alice" ; val b = "$bob""""
defs: String = val a = "Alice" ; val b = "Bob"

scala> val message = "${b} < ${a} and ${a} > ${b}"
message: String = ${b} < ${a} and ${a} > ${b}

scala> val msg = s"""s"$message""""
msg: String = s"${b} < ${a} and ${a} > ${b}"

scala> tb eval (tb parse s"$defs ; $msg")
res3: Any = Bob < Alice and Alice > Bob
scala>导入scala.tools.reflect_
导入scala.tools.reflect_
scala>val tb=reflect.runtime.currentMirror.mkToolBox()
tb:scala.tools.reflect.ToolBox[reflect.runtime.universe.type]=scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@162b3d47
scala>val defs=s“val a=“$alice”;val b=“$bob”
defs:String=val a=“Alice”;val b=“鲍勃”
scala>val message=“${b}<${a}和${a}>${b}”
消息:String=${b}<${a}和${a}>${b}
scala>val msg=s“s”$message”
msg:String=s“${b}<${a}和${a}>${b}”
scala>tb eval(tb解析s“$defs;$msg”)
res3:Any=BobBob

scala>def(a:String,b:String)=tb eval(tb parse s”““val a=“$a”val b=“$b”s“$message”“”“)
f:(a:字符串,b:字符串)任何
scala>f(a=alice,b=bob)
res4:Any=BobBob
有点太多了

但请考虑:


注意当
alice=“${b}”
时这会发生什么。为了使它更健壮,可以在执行替换之前在变量值中插入\\以转义$和\(…和其他?)。它还意外地导致一些替换是可传递的
${a}
更改为
${b}
,然后
${b}
更改为
Bob
。注意当
alice=“${b}”
时这会发生什么。为了使它更健壮,可以插入\\以跳出$and\(…和其他?)在进行替换之前,它还会意外地导致某些替换是可传递的
${a}
更改为
${b}
,然后
${b}
更改为
Bob
。你一定喜欢正则表达式。使用duck磁带、WD40和regex,您可以征服世界。哦,还要一些咖啡。嗯,还有爱和有线电视的关系,我想…你一定喜欢雷格克斯。使用duck磁带、WD40和regex,您可以征服世界。哦,还要一些咖啡。嗯,我想还有爱情和有线电视。。。