Skip to content

Scala 正则表达式

Scala 通过 scala.util.matching.Regex 类提供内置的正则表达式支持。创建 Regex 实例最符合 Scala 习惯的方式是调用 String 上的 .r 方法。

import scala.util.matching.Regex
// Using the .r method (preferred)
val simplePattern: Regex = "Scala".r
val digitPattern = "\\d+".r // Need double backslash for literal backslash in string
// Using the Regex constructor
val caseInsensitivePattern = new Regex("(?i)scala") // (?i) flag for case-insensitivity

几种方法可以让你在目标字符串中查找匹配项。

findFirstIn(target):返回一个 Option[String],其中包含第一个匹配项;如果没有找到匹配项,则返回 None。

Section titled “findFirstIn(target):返回一个 Option[String],其中包含第一个匹配项;如果没有找到匹配项,则返回 None。”
val text = "Scala is scalable and cool. scala rocks!"
val pattern = "[Ss]cala".r // Match 'Scala' or 'scala'
val firstMatch = pattern.findFirstIn(text)
println(s"First match: $firstMatch") // Output: First match: Some(Scala)

findAllIn(target):返回一个 Iterator[String],遍历所有不重叠的匹配项。

Section titled “findAllIn(target):返回一个 Iterator[String],遍历所有不重叠的匹配项。”
val allMatchesIterator = pattern.findAllIn(text)
val allMatchesList = allMatchesIterator.toList // 将迭代器转换为 List 以便更方便使用
println(s"All matches: $allMatchesList") // Output: All matches: List(Scala, scala)

你可以使用 .mkString 轻松地格式化 findAllIn 的结果:

println(s"All matches joined: ${pattern.findAllIn(text).mkString(", ")}") // Output: All matches joined: Scala, scala

findPrefixOf(target):如果正则表达式匹配目标字符串的开头,则返回一个 Option[String]。

Section titled “findPrefixOf(target):如果正则表达式匹配目标字符串的开头,则返回一个 Option[String]。”
val startsWithScala = pattern.findPrefixOf(text)
println(s"Starts with Scala?: $startsWithScala") // Output: Starts with Scala?: Some(Scala)
val otherText = "Cool Scala"
println(s"Starts with Scala?: ${pattern.findPrefixOf(otherText)}") // Output: Starts with Scala?: None

matches(target):返回一个 Boolean 值,指示 整个 目标字符串是否与正则表达式匹配。

Section titled “matches(target):返回一个 Boolean 值,指示 整个 目标字符串是否与正则表达式匹配。”
val numberPattern = "\\d{3}-\\d{4}".r // Matches XXX-XXXX format
val phone1 = "123-4567"
val phone2 = "123-456"
val phone3 = "abc-defg"
println(s"'$phone1' matches? ${numberPattern.matches(phone1)}") // Output: '123-4567' matches? true
println(s"'$phone2' matches? ${numberPattern.matches(phone2)}") // Output: '123-456' matches? false
println(s"'$phone3' matches? ${numberPattern.matches(phone3)}") // Output: 'abc-defg' matches? false

replaceFirstIn(target, replacement):替换第一个匹配项。

Section titled “replaceFirstIn(target, replacement):替换第一个匹配项。”
val replacedFirst = pattern.replaceFirstIn(text, "Java")
println(s"Replace first: $replacedFirst")
// Output: Replace first: Java is scalable and cool. scala rocks!

replaceAllIn(target, replacement):替换所有匹配项。

Section titled “replaceAllIn(target, replacement):替换所有匹配项。”
val replacedAll = pattern.replaceAllIn(text, "Python")
println(s"Replace all: $replacedAll")
// Output: Replace all: Python is scalable and cool. Python rocks!

你还可以使用一个函数作为替换内容,从而允许基于匹配项进行动态替换。

val dynamicReplace = pattern.replaceAllIn(text, m => s"[${m.matched.toUpperCase}]" )
println(s"Dynamic replace: $dynamicReplace")
// Output: Dynamic replace: [SCALA] is scalable and cool. [SCALA] rocks!

当正则表达式包含捕获组(由括号 () 定义)时,你可以提取这些被捕获的部分。

val keyValuePattern = "(\w+)=(\d+)".r // 第 1 组:键(单词),第 2 组:值(数字)
val data = "config=100, type=2, user=abc" // 注意:'user=abc' 不会匹配 \d+
println("\nExtracting key-value pairs:")
for (keyValuePattern(key, value) <- keyValuePattern.findAllIn(data)) {
println(s"Key: $key, Value: $value (as String)")
}

输出:

Extracting key-value pairs:
Key: config, Value: 100 (as String)
Key: type, Value: 2 (as String)

这在 for 推导式或 match 表达式中使用了 Regex 对象作为 提取器。keyValuePattern(key, value) 尝试匹配模式并将分组提取到 key 和 value 变量中。

Scala 使用 Java 的正则表达式语法,它与 Perl 的语法基本兼容。

语法描述
.任何单个字符(除了换行符,除非设置 DOTALL 标记)
\d数字 [0-9]
\D非数字 [^0-9]
\s空白字符 [ \t\n\x0B\f\r]
\S非空白字符
\w单词字符 [a-zA-Z_0-9]
\W非单词字符
^行/字符串的开头
$行/字符串的结尾
\b单词边界
\B非单词边界
[abc]字符类:‘a’, ‘b’, 或 ‘c’
[^abc]否定类:除了 ‘a’, ‘b’, 或 ‘c’ 之外的任何字符
[a-z]范围:任何小写字母
a|b选择:‘a’ 或 ‘b’
(…)捕获组
(?:…)非捕获组
X?量词:零个或一个 ‘X’
X*量词:零个或多个 ‘X’
X+量词:一个或多个 ‘X’
X{n}量词:恰好 ‘n’ 个 ‘X’
X{n,}量词:至少 ‘n’ 个 ‘X’
X{n,m}量词:至少 ‘n’ 个但不超过 ‘m’ 个 ‘X’

重要提示: 请记住在 Scala 字符串字面量中转义反斜杠。要匹配字面反斜杠 \,请在字符串中使用 \\。要匹配数字 \d,请使用 "\\d"。