1. 概述
正则表达式(Regular Expressions)在文本处理中非常有用。本教程将介绍 Scala 中 scala.util.matching.Regex
类的功能,并展示如何在实际开发中使用它。
2. Scala 中的 Regex 类
Scala 的 Regex
类基于 Java 的 java.util.regex
包,提供了简洁明了的 API。结合 Scala 的 模式匹配 特性,Regex
的使用更加直观、易读。
创建 Regex
对象有两种方式:
✅ 方式一:显式创建
val polishPostalCode = new Regex("([0-9]{2})\\-([0-9]{3})")
✅ 方式二:使用 r
方法(推荐,更 Scala 风格)
val polishPostalCode = "([0-9]{2})\\-([0-9]{3})".r
接下来,我们来看 Regex
的常见使用场景。
3. 查找匹配项
查找文本中的匹配内容是最常见的使用方式之一。
3.1 查找第一个匹配项
- 使用
findFirstIn
,返回Option[String]
:
val postCode = polishPostalCode.findFirstIn("Warsaw 01-011, Jerusalem Avenue")
assertEquals("01-011", postCode)
- 使用
findFirstMatchIn
,返回Option[Match]
,可以访问捕获组:
val postCodes = polishPostalCode.findFirstMatchIn("Warsaw 01-011, Jerusalem Avenue")
assertEquals(Some("011"), for (m <- postCodes) yield m.group(2))
3.2 查找所有匹配项
- 使用
findAllIn
,返回MatchIterator
:
val postCodes = polishPostalCode.findAllIn("Warsaw 01-011, Jerusalem Avenue, Cracow 30-059, Mickiewicza Avenue")
.toList
assertEquals(List("01-011", "30-059"), postCodes)
- 使用
findAllMatchIn
,返回Iterator[Match]
,可提取捕获组:
val postCodes = polishPostalCode.findAllMatchIn("Warsaw 01-011, Jerusalem Avenue, Cracow 30-059, Mickiewicza Avenue")
.toList
val postalDistricts = for (m <- postCodes) yield m.group(1)
assertEquals(List("01", "30"), postalDistricts)
4. 提取匹配值
当正则表达式匹配成功后,我们可以使用 Regex
作为提取器(Extractor)结合模式匹配来提取值:
val timestamp = "([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{3})".r
val description = "11:34:01.411" match {
case timestamp(hour, minutes, _, _) => s"It's $minutes minutes after $hour"
}
assertEquals("It's 34 minutes after 11", description)
⚠️ 默认情况下,Regex
的匹配是“锚定的”,即等价于 ^pattern$
。如果需要非锚定匹配,可以使用 unanchored
方法:
val timestampUnanchored = timestamp.unanchored
这样,即使匹配内容前后有其他字符,也能成功提取:
val description = "Timestamp: 11:34:01.411 error appeared" match {
case timestampUnanchored(hour, minutes, _, _) => s"It's $minutes minutes after $hour"
}
assertEquals("It's 34 minutes after 11", description)
5. 替换文本
正则表达式也常用于文本替换,Regex
提供了 replaceAllIn
方法支持替换操作。
✅ 基本用法:
val minutes = timestamp.replaceAllIn("11:34:01.311", m => m.group(2))
assertEquals("34", minutes)
✅ 结合模式匹配使用更灵活:
val secondsThatDayInTotal = timestamp.replaceAllIn("11:34:01.311", _ match {
case timestamp(hours, minutes, seconds, _) => s"$hours-$minutes"
})
assertEquals("11-34", secondsThatDayInTotal)
6. 小结
本文介绍了 Scala 标准库中的 Regex
类。它提供了一套非常易读、易用的 API,适用于绝大多数正则表达式的使用场景。
📌 完整源码可从 GitHub 获取。