Scala 中的嵌套字符串插值

Nested String Interpolation in Scala

我正在 RDBMS 上执行查询并将结果作为字符串获取。字符串看起来像这样:

val DBASE = "my_database"
val FREQ = "monthly"
val queryResult: String = sqlContext.read.jdbc(...).collect.map(...).first
// queryResult = Database is $$${DBASE} and frequency is $$${FREQ}

接下来我将 $$$ 替换为 $,所以我剩下的是:

queryResult = "Database is ${DBASE} and frequency is ${FREQ}"

如何在 DBASEFREQ 上使用字符串插值?我试过:

val substituted = f"${queryResult}"

val substituted = s"${queryResult}"

但是变量没有被替换。除了使用以下内容,我还能做些什么吗:

queryResult.replaceAll("\$\{DBASE\}", DBASE).replaceAll(...)

Scala 的字符串插值

s"Database is ${DBASE} and frequency is ${FREQ}"

本质上只是对 StringContext 上的方法调用的奇特语法。它脱糖成类似

的东西
StringContext("Database is ", " and frequency is ",  "").s(DBASE, FREQ)

虽然理论上您可以将字符串 "Database is ${DBASE} and frequency is ${FREQ}" 拆分为适合 StringContext 的片段,然后在某处查找变量 DBASEFREQ,但似乎立即 replaceAll 出现 $$${DBASE}$$${FREQ} 要容易得多。

我认为不可能动态地插入一个字符串,因为它发生在编译时本身。

1) 字符串插值发生在编译时,因此编译器通常没有足够的信息来插值s(queryResult)。根据 https://docs.scala-lang.org/sips/string-interpolation.html.

,它需要一个字符串文字

2) 在文档的高级用法下,解释了形式为 id"Hello $name ." 的表达式在编译时被转换为 new StringContext("Hello", ".")。 id(名字).

所以你可以创建类似

的东西
StringContext("Database is ", " and frequency is ",  "").s(DBASE, FREQ)

这将替代语法糖。希望对您有所帮助。

一种选择是让脚本编写您的模板:

     ________ ___   / /  ___  
    / __/ __// _ | / /  / _ | 
  __\ \/ /__/ __ |/ /__/ __ | 
 /____/\___/_/ |_/____/_/ | | 
                          |/  version 2.12.6

scala> import javax.script._
import javax.script._

scala> val se = new ScriptEngineManager().getEngineByName("scala")
se: javax.script.ScriptEngine = scala.tools.nsc.interpreter.Scripted@6549ce71

scala> val b = se.createBindings
b: javax.script.Bindings = javax.script.SimpleBindings@2648aa1b

scala> b.put("DBASE", "my_db")
res0: Object = null

scala> b.put("FREQ", "monthly")
res1: Object = null

scala> se.eval("""s"Db is $DBASE, freq is $FREQ"""", b)
res2: Object = Db is my_db, freq is monthly

绑定的对象类型不正确,但您可以强制转换或进行更多计算:

scala> se.eval("""s"Db is $DBASE, freq is ${FREQ.toString * 2}"""", b)
res4: Object = Db is my_db, freq is monthlymonthly