1. 概述

Kotlin 的字符串模板 是一个非常实用的特性,它允许我们在字符串中嵌入变量或表达式,Kotlin 会自动进行求值。例如:

  • "The value is: $variable"
  • "42 x 42 = ${42 * 42}"

Kotlin 字符串家族的另一个成员是 原始字符串(raw string)。原始字符串非常适合表示多行文本,且无需对特殊字符进行转义,非常适合用于正则表达式、文件路径等场景。而且,原始字符串也支持字符串模板

但有时候,我们希望字符串中的模板语法不被解析,例如我们想保留一个字面的美元符号 $ 后面跟着一些文字。这时就需要将字符串模板转义为字面字符串。

本文将介绍在 Kotlin 中实现该目的的几种方式。

2. 并非所有“$xxx”都是字符串模板

Kotlin 中的字符串模板以 $ 开头。所以,要避免模板解析,关键就在于如何转义 $ 符号

但并不是所有 $ 后面跟内容都会被当作模板。来看几个例子:

val myStr1 = "The new iPhone's price is from $999"
val myStr2 = "The new iPhone's price is from $ 999"
val myStr3 = "The new iPhone's price is from 999$"

这三个字符串中的 $ 都被当作字面字符处理,无需任何转义。因为 $ 后面的内容不是一个合法的 Kotlin 变量名,所以不会被识别为模板。

结论:只有当 $ 后接合法变量名或表达式时,才会被当作模板解析。

3. 转义 $ 字符

最直接的方法就是使用反斜杠 \ 来转义 $

val myStr = "In shell script, \${ parameter } is called parameter substitution."

✅ 该方式适用于普通字符串,但 不适用于原始字符串,因为在原始字符串中,反斜杠不会被当作转义字符处理。

❌ 以下代码会报错:

val myRawStr = """In shell script, \${ parameter } is called parameter substitution."""

编译器会提示:Unresolved reference: parameter,因为它仍然尝试解析 ${ parameter } 为模板。

解决方案:在原始字符串中,可以将转义部分放入变量中:

val myVar = "\${ parameter }"
val myRawStr = """In shell script, $myVar is called parameter substitution."""

这样虽然可行,但略显繁琐。

4. 使用 Kotlin 标识符 ${'$'}

除了使用反斜杠转义,还有一种更通用的方法:使用 Kotlin 的标识符 ${'$'} 来表示一个字面的 $ 字符。

这种方式适用于普通字符串和原始字符串:

val mySingleStr = "In shell script, ${'$'}{ parameter } is called parameter substitution."
val myRawStr = """In shell script, ${'$'}{ parameter } is called parameter substitution."""

优点

  • 不需要引入额外变量
  • 更加直观和安全
  • 适用于所有字符串类型(单行字符串、原始字符串)

⚠️ 踩坑提示:如果你的字符串中包含大量 $,比如正则表达式或 shell 脚本片段,推荐使用这种方式,避免手动转义带来的错误。

5. 小结

本文我们学习了两种方法来避免 Kotlin 字符串模板被解析:

方法 描述 适用场景
\$ 使用反斜杠转义 $ 单行字符串
${'$'} 使用 Kotlin 标识符表示字面 $ 所有字符串类型(推荐)

两种方法都能达到目的,但在原始字符串中更推荐使用 ${'$'},因为它更简洁、直观,也更不容易出错。


完整示例代码可以在 GitHub 上找到。


原始标题:How to Turn String Templates Into Literal Strings