Scala 正则表达式
在 Scala 编程语言中,正则表达式(Regular Expressions,简称 Regex) 是一种强大的工具,用于匹配、搜索、替换或验证字符串中的模式。Scala 提供了对正则表达式的内置支持,主要通过 scala.util.matching.Regex
类实现。本文将详细讲解 Scala 中正则表达式的使用,包括基本概念、语法、常用方法以及实际应用场景,适合初学者和有一定经验的开发者。
1. 什么是正则表达式?
正则表达式是一组定义字符串模式的规则,用于匹配字符串中的特定内容。例如,你可以用正则表达式来验证电子邮件地址、提取电话号码或替换文本中的特定单词。Scala 的正则表达式基于 Java 的 java.util.regex
包,因此其语法与 Java 和其他语言中的正则表达式类似。
在 Scala 中,正则表达式通常通过 scala.util.matching.Regex
类来创建和操作。
2. 创建正则表达式
在 Scala 中,有两种主要方式创建正则表达式:
- 使用
Regex
类:通过scala.util.matching.Regex
构造器创建。 - 使用三引号字符串和
.r
方法:这是 Scala 中更简洁的方式。
2.1 使用 Regex
类
import scala.util.matching.Regex
val pattern = new Regex("\\d+")
这里 \\d+
表示匹配一个或多个数字。
2.2 使用 .r
方法
Scala 提供了更简洁的方式,通过在字符串后调用 .r
方法将字符串转换为 Regex
对象:
val pattern = "\\d+".r
使用三引号 """
可以避免手动转义反斜杠:
val pattern = """\d+""".r
注意事项
- 反斜杠
\
在字符串中需要双写(\\
),因为 Scala 字符串需要转义。 - 三引号字符串
"""
可以直接写正则表达式,避免繁琐的转义。
3. 常用正则表达式语法
以下是一些常见的正则表达式模式,适用于 Scala:
模式 | 描述 | 示例 |
---|---|---|
\d | 匹配一个数字 | 123 |
\D | 匹配一个非数字 | abc |
\w | 匹配一个字母、数字或下划线 | a1_ |
\W | 匹配一个非字母、数字或下划线 | @# |
\s | 匹配一个空白字符(空格、制表符等) | |
. | 匹配任意字符(除了换行符) | a , 1 , @ |
^ | 匹配字符串开头 | ^hello |
$ | 匹配字符串结尾 | world$ |
* | 匹配 0 次或多次 | a* (匹配 "" , a , aa 等) |
+ | 匹配 1 次或多次 | a+ (匹配 a , aa 等) |
? | 匹配 0 次或 1 次 | a? (匹配 "" 或 a ) |
{n} | 匹配恰好 n 次 | a{3} (匹配 aaa ) |
{n,m} | 匹配 n 到 m 次 | a{2,4} (匹配 aa , aaa , aaaa ) |
(pattern) | 捕获组,用于提取匹配的部分 | (\d+) (捕获数字) |
| | 或运算,匹配多个模式 | cat|dog (匹配 cat 或 dog ) |
示例:匹配电子邮件
val emailPattern = """\w+@\w+\.\w+""".r
val text = "Contact us at alice@example.com or bob@company.org"
emailPattern.findAllIn(text).foreach(println)
// 输出:
// alice@example.com
// bob@company.org
4. 常用方法
Scala 的 Regex
类提供了多种方法来操作正则表达式。以下是常用的方法:
4.1 findFirstIn
查找字符串中第一个匹配的子字符串,返回 Option[String]
。
val pattern = """\d+""".r
val text = "My number is 123 and 456"
val result = pattern.findFirstIn(text) // 返回 Some("123")
println(result.getOrElse("No match")) // 输出:123
4.2 findAllIn
查找字符串中所有匹配的子字符串,返回一个迭代器(Iterator[String]
)。
val pattern = """\d+""".r
val text = "My number is 123 and 456"
pattern.findAllIn(text).foreach(println)
// 输出:
// 123
// 456
4.3 replaceAllIn
将字符串中所有匹配的部分替换为指定内容。
val pattern = """\d+""".r
val text = "My number is 123 and 456"
val result = pattern.replaceAllIn(text, "XXX")
println(result) // 输出:My number is XXX and XXX
4.4 findFirstMatchIn
返回第一个匹配的详细信息(Option[Match]
),包括捕获组等。
val pattern = """(\w+)@(\w+)\.(\w+)""".r
val text = "Contact: alice@example.com"
val matchOption = pattern.findFirstMatchIn(text)
matchOption match {
case Some(m) => println(s"User: ${m.group(1)}, Domain: ${m.group(2)}, Suffix: ${m.group(3)}")
case None => println("No match")
}
// 输出:User: alice, Domain: example, Suffix: com
4.5 模式匹配中的正则表达式
正则表达式可以与 Scala 的模式匹配结合使用,通过捕获组提取数据。
val pattern = """(\w+)@(\w+)\.(\w+)""".r
val email = "alice@example.com"
email match {
case pattern(user, domain, suffix) => println(s"User: $user, Domain: $domain, Suffix: $suffix")
case _ => println("Invalid email")
}
// 输出:User: alice, Domain: example, Suffix: com
5. 使用捕获组
捕获组是正则表达式中用括号 ()
包裹的部分,用于提取匹配的子字符串。捕获组从 1 开始编号,group(0)
表示整个匹配的字符串。
示例:解析日期
val datePattern = """(\d{4})-(\d{2})-(\d{2})""".r
val text = "Today is 2025-09-07"
text match {
case datePattern(year, month, day) => println(s"Year: $year, Month: $month, Day: $day")
case _ => println("Invalid date")
}
// 输出:Year: 2025, Month: 09, Day: 07
6. 常见使用场景
- 验证输入:检查字符串是否符合特定格式,如电子邮件、电话号码。
- 提取数据:从文本中提取特定信息,如 URL、日期等。
- 替换文本:将匹配的部分替换为新内容,如屏蔽敏感词。
- 分词:将字符串按特定模式分割。
示例:验证电话号码
val phonePattern = """\d{3}-\d{3}-\d{4}""".r
def isValidPhone(phone: String): Boolean = phonePattern.findFirstIn(phone).isDefined
println(isValidPhone("123-456-7890")) // 输出:true
println(isValidPhone("123-456-789")) // 输出:false
示例:分割字符串
val text = "apple,banana,orange"
val pattern = """,""".r
val fruits = pattern.split(text)
fruits.foreach(println)
// 输出:
// apple
// banana
// orange
7. 注意事项
- 性能:正则表达式可能对性能敏感,尤其是复杂模式或长字符串。避免在高频循环中使用复杂正则。
- 转义字符:在 Scala 字符串中,反斜杠需要双写(
\\
)。使用三引号"""
可以减少转义的麻烦。 - 异常处理:正则表达式可能抛出
PatternSyntaxException
,确保在必要时捕获异常。 - 贪婪与非贪婪:默认情况下,正则表达式是贪婪匹配(尽量匹配更多字符)。使用
?
可以改为非贪婪匹配。
val pattern = """<.*?>""".r // 非贪婪匹配 HTML 标签
val text = "<p>Hello</p><div>World</div>"
pattern.findAllIn(text).foreach(println)
// 输出:
// <p>
// </p>
// <div>
// </div>
8. 总结
Scala 的正则表达式通过 scala.util.matching.Regex
提供了强大的字符串处理能力,结合 .r
方法和模式匹配,语法简洁且功能丰富。无论是验证输入、提取数据还是替换文本,正则表达式在 Scala 中都非常实用。通过捕获组和模式匹配的结合,开发者可以轻松处理复杂的字符串操作。
如果你有具体的正则表达式问题或需要更详细的示例(例如处理特定格式的文本),请告诉我,我可以提供进一步的帮助!