Skip to content

Scala 转义字符

转义字符是在字符串和字符字面量中表示特殊字符的方式。本章将详细介绍 Scala 中各种转义字符的使用方法。

转义字符概述

转义字符以反斜杠 \ 开头,用于表示无法直接输入或具有特殊含义的字符。

基本转义字符

scala
// 常用转义字符
val tab = '\t'          // 制表符 (Tab)
val newline = '\n'      // 换行符 (Line Feed)
val carriageReturn = '\r' // 回车符 (Carriage Return)
val backspace = '\b'    // 退格符 (Backspace)
val formFeed = '\f'     // 换页符 (Form Feed)
val singleQuote = '\''  // 单引号
val doubleQuote = '\"'  // 双引号
val backslash = '\\'    // 反斜杠

// 在字符串中使用
val message = "Hello\tWorld\nThis is a new line"
val path = "C:\\Users\\username\\Documents"
val quote = "He said \"Hello\" to me"

字符转义字符

可打印字符转义

scala
// 单引号在字符字面量中需要转义
val singleQuoteChar = '\''

// 双引号在字符字面量中需要转义
val doubleQuoteChar = '\"'

// 反斜杠需要转义
val backslashChar = '\\'

// 示例
println(singleQuoteChar)  // '
println(doubleQuoteChar)  // "
println(backslashChar)    // \

控制字符转义

scala
// 制表符
val tab = '\t'
println(s"Name${tab}Age${tab}City")
// 输出: Name    Age    City

// 换行符
val newline = '\n'
println(s"First Line${newline}Second Line")
// 输出:
// First Line
// Second Line

// 回车符 (通常与换行符一起使用)
val crlf = "\r\n"  // Windows 风格的行结束符

// 退格符
val backspace = '\b'
println(s"Hello${backspace} World")  // 删除一个字符

// 换页符
val formFeed = '\f'
println(s"Page 1${formFeed}Page 2")  // 换页

字符串转义字符

在普通字符串中使用转义

scala
// 包含转义字符的字符串
val text1 = "Line 1\nLine 2\nLine 3"
val text2 = "Column1\tColumn2\tColumn3"
val text3 = "She said \"Hello\" to him"
val text4 = "File path: C:\\Program Files\\MyApp"

println(text1)
// 输出:
// Line 1
// Line 2
// Line 3

println(text2)
// 输出: Column1    Column2    Column3

println(text3)
// 输出: She said "Hello" to him

println(text4)
// 输出: File path: C:\Program Files\MyApp

转义字符组合

scala
// 多种转义字符组合使用
val formatted = "Name:\t\"John Doe\"\nAge:\t25\nCity:\t\"New York\""
println(formatted)
// 输出:
// Name:    "John Doe"
// Age:     25
// City:    "New York"

// 表格格式
val table = "ID\tName\t\tSalary\n" +
           "1\tAlice\t\t$50,000\n" +
           "2\tBob\t\t$60,000\n" +
           "3\tCharlie\t$55,000"
println(table)

Unicode 转义字符

基本 Unicode 转义

scala
// Unicode 转义格式: \uXXXX (4位十六进制)
val unicodeA = '\u0041'      // 'A'
val unicodeHeart = '\u2764'  // ❤
val unicodeSmiley = '\u263A' // ☺
val unicodeChinese = '\u4E2D' // 中

println(s"Unicode A: $unicodeA")
println(s"Heart: $unicodeHeart")
println(s"Smiley: $unicodeSmiley")
println(s"Chinese: $unicodeChinese")

// 在字符串中使用 Unicode
val greeting = "Hello \u4E16\u754C"  // Hello 世界
println(greeting)

常用 Unicode 字符

scala
// 数学符号
val pi = '\u03C0'           // π
val infinity = '\u221E'     // ∞
val sum = '\u2211'          // ∑
val integral = '\u222B'     // ∫

// 货币符号
val dollar = '\u0024'       // $
val euro = '\u20AC'         // €
val yen = '\u00A5'          // ¥
val pound = '\u00A3'        // £

// 箭头符号
val leftArrow = '\u2190'    // ←
val rightArrow = '\u2192'   // →
val upArrow = '\u2191'      // ↑
val downArrow = '\u2193'    // ↓

// 创建包含各种符号的字符串
val symbols = s"Math: $pi $infinity $sum | Currency: $dollar $euro $yen | Arrows: $leftArrow $rightArrow"
println(symbols)

中文字符 Unicode

scala
// 常用中文字符的 Unicode
val chinese = Map(
  "你" -> '\u4F60',
  "好" -> '\u597D',
  "世" -> '\u4E16',
  "界" -> '\u754C',
  "中" -> '\u4E2D',
  "国" -> '\u56FD'
)

// 使用 Unicode 构建中文字符串
val hello = s"${chinese("你")}${chinese("好")}"
val world = s"${chinese("世")}${chinese("界")}"
val china = s"${chinese("中")}${chinese("国")}"

println(s"$hello $world")  // 你好 世界
println(china)             // 中国

八进制转义字符

八进制转义格式

scala
// 八进制转义格式: \nnn (1-3位八进制数字)
val octalA = '\101'         // 'A' (八进制101 = 十进制65)
val octalNewline = '\012'   // '\n' (八进制12 = 十进制10)
val octalTab = '\011'       // '\t' (八进制11 = 十进制9)
val octalNull = '\0'        // null字符 (八进制0 = 十进制0)

println(s"Octal A: $octalA")
println(s"Octal newline creates new line:$octalNewline")
println(s"Octal${octalTab}tab")

// 八进制数字范围
val octal1 = '\1'           // 1位八进制
val octal12 = '\12'         // 2位八进制
val octal123 = '\123'       // 3位八进制 (十进制83, 字符'S')

println(s"Octal 123 represents: $octal123")

原始字符串中的转义

原始字符串特性

scala
// 原始字符串(三重引号)中不需要转义
val rawString = """This is a raw string.
It can contain "quotes" and \backslashes
without escaping them.
Even \n and \t are literal characters."""

println(rawString)

// 对比普通字符串
val normalString = "This needs escaping: \"quotes\" and \\backslashes\nNew line here"
println(normalString)

// 正则表达式中的应用
val emailRegex = """[\w\.-]+@[\w\.-]+\.\w+"""  // 不需要双重转义
val pathRegex = """C:\\Users\\[^\\]+\\Documents"""  // 仍然需要转义反斜杠

// 对比普通字符串中的正则表达式
val emailRegexNormal = "[\\w\\.-]+@[\\w\\.-]+\\.\\w+"  // 需要双重转义

字符串插值中的转义

s 插值器中的转义

scala
val name = "Alice"
val age = 25

// 在 s 插值器中使用转义字符
val message1 = s"Name:\t$name\nAge:\t$age"
println(message1)

// 转义插值表达式中的特殊字符
val price = 19.99
val currency = "$"
val formatted = s"Price: \\$price $currency"  // 转义 $ 符号
println(formatted)  // Price: $price $

// 正确的方式
val correctFormatted = s"Price: $currency$price"
println(correctFormatted)  // Price: $19.99

f 插值器中的转义

scala
val pi = math.Pi
val percentage = 0.856

// f 插值器中的转义
val formatted1 = f"Pi: $pi%.2f\nPercentage: ${percentage * 100}%.1f%%"
println(formatted1)
// 输出:
// Pi: 3.14
// Percentage: 85.6%

// 转义百分号
val progress = 75
val progressMsg = f"Progress: $progress%%"  // %% 表示字面量 %
println(progressMsg)  // Progress: 75%

raw 插值器中的转义

scala
val path = "Documents"
val user = "Alice"

// raw 插值器不处理转义字符
val rawPath = raw"C:\Users\$user\$path"
println(rawPath)  // C:\Users\Alice\Documents

// 对比 s 插值器
val sPath = s"C:\\Users\\$user\\$path"
println(sPath)    // C:\Users\Alice\Documents

// raw 插值器中的换行符
val rawMultiline = raw"Line 1\nLine 2\tTabbed"
println(rawMultiline)  // Line 1\nLine 2\tTabbed (字面量)

val sMultiline = s"Line 1\nLine 2\tTabbed"
println(sMultiline)
// 输出:
// Line 1
// Line 2    Tabbed

实际应用示例

日志格式化

scala
object Logger {
  def formatLogEntry(level: String, component: String, message: String): String = {
    val timestamp = java.time.LocalDateTime.now()
    s"[$timestamp]\t$level\t$component:\t$message"
  }
  
  def info(component: String, message: String): Unit = {
    println(formatLogEntry("INFO", component, message))
  }
  
  def error(component: String, message: String): Unit = {
    println(formatLogEntry("ERROR", component, message))
  }
  
  def debug(component: String, message: String): Unit = {
    println(formatLogEntry("DEBUG", component, message))
  }
}

// 使用示例
Logger.info("Database", "Connection established")
Logger.error("API", "Request failed with status 500")
Logger.debug("Cache", "Cache hit for key \"user:123\"")

CSV 数据处理

scala
object CSVProcessor {
  def createCSVRow(fields: String*): String = {
    fields.map { field =>
      if (field.contains(",") || field.contains("\"") || field.contains("\n")) {
        // 包含特殊字符的字段需要用引号包围,内部引号需要转义
        "\"" + field.replace("\"", "\"\"") + "\""
      } else {
        field
      }
    }.mkString(",")
  }
  
  def parseCSVRow(row: String): List[String] = {
    // 简化的 CSV 解析(实际应用中建议使用专门的库)
    row.split(",").map(_.trim.stripPrefix("\"").stripSuffix("\"")).toList
  }
}

// 使用示例
val csvData = List(
  CSVProcessor.createCSVRow("John Doe", "30", "Engineer", "\"Hello, World!\""),
  CSVProcessor.createCSVRow("Jane Smith", "25", "Designer", "Creative\nThinker"),
  CSVProcessor.createCSVRow("Bob Johnson", "35", "Manager", "Team Leader")
)

csvData.foreach(println)
// 输出:
// John Doe,30,Engineer,"""Hello, World!"""
// Jane Smith,25,Designer,"Creative
// Thinker"
// Bob Johnson,35,Manager,Team Leader

配置文件生成

scala
object ConfigGenerator {
  def generateProperties(config: Map[String, String]): String = {
    val header = "# Application Configuration\n# Generated on " + 
                java.time.LocalDateTime.now() + "\n\n"
    
    val properties = config.map { case (key, value) =>
      // 转义属性值中的特殊字符
      val escapedValue = value
        .replace("\\", "\\\\")  // 反斜杠
        .replace("\n", "\\n")   // 换行符
        .replace("\r", "\\r")   // 回车符
        .replace("\t", "\\t")   // 制表符
        .replace("=", "\\=")    // 等号
        .replace(":", "\\:")    // 冒号
      
      s"$key=$escapedValue"
    }.mkString("\n")
    
    header + properties
  }
}

// 使用示例
val appConfig = Map(
  "app.name" -> "My Scala App",
  "app.version" -> "1.0.0",
  "database.url" -> "jdbc:postgresql://localhost:5432/mydb",
  "log.pattern" -> "%d{yyyy-MM-dd HH:mm:ss} [%level] %logger{36} - %msg%n",
  "file.path" -> "C:\\Program Files\\MyApp\\data"
)

val propertiesContent = ConfigGenerator.generateProperties(appConfig)
println(propertiesContent)

JSON 字符串处理

scala
object JSONEscaper {
  def escapeJSONString(str: String): String = {
    str
      .replace("\\", "\\\\")  // 反斜杠
      .replace("\"", "\\\"")  // 双引号
      .replace("\b", "\\b")   // 退格符
      .replace("\f", "\\f")   // 换页符
      .replace("\n", "\\n")   // 换行符
      .replace("\r", "\\r")   // 回车符
      .replace("\t", "\\t")   // 制表符
  }
  
  def createJSONString(key: String, value: String): String = {
    s""""${escapeJSONString(key)}": "${escapeJSONString(value)}""""
  }
  
  def createJSONObject(fields: Map[String, String]): String = {
    val jsonFields = fields.map { case (key, value) =>
      createJSONString(key, value)
    }.mkString(",\n  ")
    
    s"{\n  $jsonFields\n}"
  }
}

// 使用示例
val userData = Map(
  "name" -> "John \"Johnny\" Doe",
  "bio" -> "Software engineer\nLoves coding\tand coffee",
  "website" -> "https://johndoe.com/path?param=value",
  "notes" -> "Special chars: \\ / \" \n \t"
)

val jsonString = JSONEscaper.createJSONObject(userData)
println(jsonString)

练习

练习 1:转义字符识别

scala
object EscapeCharacterExercise {
  def analyzeString(input: String): Unit = {
    println(s"Original string: \"$input\"")
    println(s"Length: ${input.length}")
    
    val escapeChars = input.zipWithIndex.collect {
      case ('\t', i) => s"Tab at position $i"
      case ('\n', i) => s"Newline at position $i"
      case ('\r', i) => s"Carriage return at position $i"
      case ('\\', i) => s"Backslash at position $i"
      case ('\"', i) => s"Double quote at position $i"
    }
    
    if (escapeChars.nonEmpty) {
      println("Escape characters found:")
      escapeChars.foreach(println)
    } else {
      println("No escape characters found")
    }
    
    println(s"Displayed string:\n$input")
    println("-" * 40)
  }
  
  def main(args: Array[String]): Unit = {
    val testStrings = List(
      "Hello\tWorld",
      "Line 1\nLine 2",
      "Path: C:\\Users\\John",
      "He said \"Hello\"",
      "Normal string without escapes",
      "Mixed:\tTab\nNewline\\Backslash\"Quote"
    )
    
    testStrings.foreach(analyzeString)
  }
}

练习 2:Unicode 字符处理

scala
object UnicodeExercise {
  // Unicode 范围定义
  val unicodeRanges = Map(
    "Basic Latin" -> (0x0000 to 0x007F),
    "CJK Unified Ideographs" -> (0x4E00 to 0x9FFF),
    "Mathematical Operators" -> (0x2200 to 0x22FF),
    "Currency Symbols" -> (0x20A0 to 0x20CF),
    "Arrows" -> (0x2190 to 0x21FF)
  )
  
  def analyzeUnicodeString(str: String): Unit = {
    println(s"Analyzing: \"$str\"")
    
    str.foreach { char =>
      val codePoint = char.toInt
      val unicodeName = unicodeRanges.find { case (_, range) =>
        range.contains(codePoint)
      }.map(_._1).getOrElse("Other")
      
      println(f"'$char' -> U+$codePoint%04X ($unicodeName)")
    }
    println()
  }
  
  def createUnicodeDemo(): String = {
    val mathSymbols = "\u03C0\u221E\u2211\u222B"  // π∞∑∫
    val currencies = "\u0024\u20AC\u00A5\u00A3"   // $€¥£
    val arrows = "\u2190\u2192\u2191\u2193"       // ←→↑↓
    val chinese = "\u4F60\u597D\u4E16\u754C"     // 你好世界
    
    s"Math: $mathSymbols | Money: $currencies | Arrows: $arrows | Chinese: $chinese"
  }
  
  def main(args: Array[String]): Unit = {
    val demo = createUnicodeDemo()
    analyzeUnicodeString(demo)
    
    // 测试其他字符串
    analyzeUnicodeString("Hello 世界!")
    analyzeUnicodeString("Price: $19.99 €15.50")
  }
}

总结

本章详细介绍了 Scala 中转义字符的使用:

  • 基本转义字符\t\n\r\\\"\'
  • Unicode 转义\uXXXX 格式表示 Unicode 字符
  • 八进制转义\nnn 格式表示八进制字符
  • 字符串中的转义:普通字符串 vs 原始字符串
  • 字符串插值中的转义:s、f、raw 插值器的不同行为
  • 实际应用:日志格式化、CSV 处理、JSON 生成等

掌握转义字符的使用对于处理文本数据、格式化输出和字符串操作非常重要。在下一章中,我们将学习 Scala 访问修饰符,了解如何控制类和成员的访问权限。

本站内容仅供学习和研究使用。