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 获取。


原始标题:Regular Expressions in Scala

« 上一篇: Scala 中的模式匹配