转义字符、多行字符串及其他

转义字符

在Scala中,也支持如下的转义字符:

FF
转义字符 Unicod编码 说明
\b \u0008 退格(BS),将当前位置移到前一列
\t \u0009 水平制表(HT),跳到下一个TAB位置
\n \u000a 换行(LF),将当前位置移到下一行开头
\f \u000c 换页(FF),将当前位置移到下页开头
\r \u000d 回车(CR),将当前位置移到本行开头
\" \u0022 代表一个双引号(")字符
\' \u0027 代表一个单引号(')字符
\\ \u005c 代表一个反斜线(\)字符

例如,我们使用json字符串来表示一个产品:

object demo {
  def main(args: Array[String]): Unit = {
    // 使用转义字符
    println("\n使用反斜杠来转义引号")
    val donutJson: String ="{\"fruit_name\":\"苹果\",\"味道\":\"肯定很美味\",\"price\":2.50}"
    println(s"donutJson = $donutJson")
  }
}

使用反斜杠(\)来转义字符很容易,但是如果有更长的文本转义,这样对一个一个字符进行转义是非常啰嗦的,因为必须转义JSON字符串中每一个单独的引用。那么,是否有更简单的方法呢?

多行字符串

在Scala中,可以通过三个双引号将文本包围起来创建创建多行字符串:

val text = """This is
a multiline
String"""

如下所示:

使用三引号,可以很容易地转义字符。请看下面的示例:

object demo {
  def main(args: Array[String]): Unit = {
    // 使用多行字符串来禁用转义字符
    println("\n使用三引号\"\"\"来转义字符")
    val fruitJson: String = """{"fruit_name":"苹果","味道":"肯定很美味","price":2.50}"""
    println(s"fruitJson = $fruitJson")
  }
}

输出结果如下所示:

使用三引号"""来转义字符
donutJson = {"fruit_name":"苹果","味道":"肯定很美味","price":2.50}

在转义引号和其他符号时,使用"""应该是一个不错的方法。但是类似于json这样的半结构化数据,程序员们更希望有较好的易读性,即以多行json格式表示。例如:

object demo03 {
  def main(args: Array[String]): Unit = {

    // 使用多行字符串来转义字符
    println("\n使用三引号\"\"\"来转义字符")
    val fruitJson: String =
      """
        |{
        |"fruit_name":"苹果",
        |"味道":"肯定很美味",
        |"price":2.50
        |}
        |""".stripMargin

    println(s"fruitJson = $fruitJson")
  }
}

输出结果如下所示:

使用三引号"""来转义字符
fruitJson = 
{
"fruit_name":"苹果",
"味道":"肯定很美味",
"price":2.50
}

另外,还可以使用三引号来创建多行SQL字符串。例如:

object demo {
  def main(args: Array[String]): Unit = {
    
    // 创建多行字符串
    val sql =
      """
        |select id,name,title,price
        |from tb
        |where id="u123" and price=234.50
      """.stripMargin
    
    println(sql)
  }
}

输出结果如下所示:

select id,name,title,price
from tb
where id="u123" and price=234.50

上面代码中多行字符串调用了stripMargin函数。如果查看stripMargin函数的定义,会发现它也接受一个参数,允许指定除默认管道|之外的其他字符。例如:

object demo {
  def main(args: Array[String]): Unit = {
    
    println("\n技巧: stripMargin使用一个不同的字符")
    val sql =
      """
          #select id,name,title,price
          #from tb
          #where id="u123" and price=234.50
      """.stripMargin('#')

    println(sql)
  }
}

输出结果如下所示:

select id,name,title,price
from tb
where id="u123" and price=234.50

逐字符处理字符串

处理字符串,一次一个字符,如下所示:

// 迭代字符串中的每个字符
val upper = "hello, world".map(c => c.toUpper)
println(upper)

val upper2 = "hello, world".map(_.toUpper)
println(upper2)

val upper3 = "hello, world".filter(_ != 'l').map(_.toUpper)
println(upper3)
     
// for/yield循环生成新的字符串,等价于前两个map
val upper4 = for (c <- "hello, world") yield c.toUpper
println(upper4)

// for/yield加上过滤
val result4 = for {
      c <- "hello, world"
      if c != 'l'
} yield c.toUpper
println(result4) 

《Spark原理深入与编程实战》