在斯卡拉实现Scala风格的字符串插值
我想在斯卡拉实现一个Scala风格的字符串插值。下面是一个例子,在斯卡拉实现Scala风格的字符串插值
val str = "hello ${var1} world ${var2}"
在运行时,我想用一些运行时字符串替换“$ {var1}”和“$ {var2}”。然而,欲以Regex.replaceAllIn时(目标:CharSequence中,替代品:(比赛)⇒字符串),我遇到了以下问题:
import scala.util.matching.Regex
val placeholder = new Regex("""(\$\{\w+\})""")
placeholder.replaceAllIn(str, m => s"A${m.matched}B")
java.lang.IllegalArgumentException: No group with name {var1}
at java.util.regex.Matcher.appendReplacement(Matcher.java:800)
at scala.util.matching.Regex$Replacement$class.replace(Regex.scala:722)
at scala.util.matching.Regex$MatchIterator$$anon$1.replace(Regex.scala:700)
at scala.util.matching.Regex$$anonfun$replaceAllIn$1.apply(Regex.scala:410)
at scala.util.matching.Regex$$anonfun$replaceAllIn$1.apply(Regex.scala:410)
at scala.collection.Iterator$class.foreach(Iterator.scala:743)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1174)
at scala.util.matching.Regex.replaceAllIn(Regex.scala:410)
... 32 elided
然而,当我从正则表达式中删除“$”,它的工作原理:
val placeholder = new Regex("""(\{\w+\})""")
placeholder.replaceAllIn(str, m => s"A${m.matched}B")
res2: String = hello $A{var1}B world $A{var2}B
所以我的问题是,这是否是在Scala正则表达式中的错误。如果是这样,是否还有其他优雅的方式来实现相同的目标(除了残酷的力量全部替换所有占位符)?
$
是替代字符串中特别处理的。这在the documentationreplaceAllIn
的描述:
在替换字符串,美元符号($),接着是多个将通过对应于9被解释为对在匹配的模式的一组参考,有数字1前九个小组,0代表整场比赛。任何其他字符都是错误的。反斜杠(
\
)字符将被解释为转义字符并可用于转义美元符号。使用Regex.quoteReplacement来转义这些字符。
(事实上,这并没有提到命名组引用,所以我想这是只有排序记录。)
总之,这里的外卖是,你一定要逃逸的的$
字符替换字符串,如果你不希望他们被视为引用。
new scala.util.matching.Regex("""(\$\{\w+\})""")
.replaceAllIn("hello ${var1} world ${var2}", m => s"A\\${m.matched}B")
// "hello A${var1}B world A${var2}B"
很难说出你期望的行为。问题是s"${m.matched}"
正在变成"${var1}"
(和"${var2}"
)。 '$'是特殊字符,表示“将组名称{var1}放置在此处”。
例如:
scala> placeholder.replaceAllIn(str, m => "$1")
res0: String = hello ${var1} world ${var2}
它取代了匹配与所述第一捕获组(这是m
本身)。
很难告诉你正在做的什么,但你可以逃脱像这样的任何$:
scala> placeholder.replaceAllIn(str, m => s"${m.matched.replace("$","\\$")}")
res1: String = hello ${var1} world ${var2}
如果你真的想要做的是评估VAR1/VAR2在局部范围内的一些变量的方法;这是不可能的。实际上,s"Hello, $name"
模式实际上在编译时转换为new StringContext("Hello, ", "").s(name)
。
是的,这正是问题所在。谢谢。 – 2014-11-04 22:31:51
对于那些对我所做的字符串插值有兴趣的人。我有一个地图,所有占位符都可以替换。例如, VAL PARAMS =地图( “$ {VAR1}” - > “富”, “$ {VAR2}” - > “栏”) 然后将下面的作品完美地串插 “” “(\ $ \ {\ w + \})”“”。r.replaceAllIn(str,m => params.get(m.matched).getOrElse(“”)) – 2014-11-04 22:40:29