Scala 正则表达式



本章解释了 Scala 如何通过 `scala.util.matching` 包中提供的 **Regex** 类支持正则表达式。

尝试以下示例程序,我们将尝试从语句中找出单词 **Scala**。

示例

import scala.util.matching.Regex

object Demo {
   def main(args: Array[String]) {
      val pattern = "Scala".r
      val str = "Scala is Scalable and cool"
      
      println(pattern findFirstIn str)
   }
}

将上述程序保存为 **Demo.scala**。以下命令用于编译和执行此程序。

命令

\>scalac Demo.scala
\>scala Demo

输出

Some(Scala)

我们创建一个字符串并在其上调用 `r()` 方法。Scala 会隐式地将字符串转换为 RichString 并调用该方法以获取 Regex 实例。要查找正则表达式的第一个匹配项,只需调用 `findFirstIn()` 方法。如果我们想查找匹配单词的所有出现而不是只查找第一次出现,我们可以使用 `findAllIn()` 方法,如果目标字符串中有多个 Scala 单词,这将返回所有匹配单词的集合。

您可以使用 `mkString()` 方法连接结果列表,并且可以使用管道符 (|) 搜索 Scala 的小写和大写形式,并且可以使用 **Regex** 构造函数或 `r()` 方法来创建模式。

尝试以下示例程序。

示例

import scala.util.matching.Regex

object Demo {
   def main(args: Array[String]) {
      val pattern = new Regex("(S|s)cala")
      val str = "Scala is scalable and cool"
      
      println((pattern findAllIn str).mkString(","))
   }
}

将上述程序保存为 **Demo.scala**。以下命令用于编译和执行此程序。

命令

\>scalac Demo.scala
\>scala Demo

输出

Scala,scala

如果要替换匹配的文本,我们可以使用 `replaceFirstIn()` 替换第一个匹配项或使用 `replaceAllIn()` 替换所有出现。

示例

object Demo {
   def main(args: Array[String]) {
      val pattern = "(S|s)cala".r
      val str = "Scala is scalable and cool"
      
      println(pattern replaceFirstIn(str, "Java"))
   }
}

将上述程序保存为 **Demo.scala**。以下命令用于编译和执行此程序。

命令

\>scalac Demo.scala
\>scala Demo

输出

Java is scalable and cool

形成正则表达式

Scala 从 Java 继承其正则表达式语法,而 Java 又继承了 Perl 的大部分特性。以下只是一些示例,作为复习应该足够了:

下表列出了 Java 中可用的所有正则表达式元字符语法。

子表达式 匹配
^ 匹配行首。
$ 匹配行尾。
. 匹配除换行符之外的任何单个字符。使用 m 选项允许它也匹配换行符。
[...] 匹配括号中的任何单个字符。
[^...] 匹配括号中不存在的任何单个字符
\\A 整个字符串的开头
\\z 整个字符串的结尾
\\Z 整个字符串的结尾,但允许最终换行符。
re* 匹配前面表达式的 0 次或多次出现。
re+ 匹配前面表达式的 1 次或多次出现
re? 匹配前面表达式的 0 次或 1 次出现。
re{ n} 匹配前面表达式的正好 n 次出现。
re{ n,} 匹配前面表达式的 n 次或多次出现。
re{ n, m} 匹配前面表达式的至少 n 次最多 m 次出现。
a|b 匹配 a 或 b。
(re) 对正则表达式进行分组并记住匹配的文本。
(?: re) 对正则表达式进行分组而不记住匹配的文本。
(?> re) 匹配不回溯的独立模式。
\\w 匹配单词字符。
\\W 匹配非单词字符。
\\s 匹配空格。等效于 [\t\n\r\f]。
\\S 匹配非空格。
\\d 匹配数字。等效于 [0-9]。
\\D 匹配非数字。
\\A 匹配字符串的开头。
\\Z 匹配字符串的结尾。如果存在换行符,则匹配换行符之前的字符。
\\z 匹配字符串的结尾。
\\G 匹配上次匹配结束的位置。
\\n 反向引用到捕获组编号“n”
\\b 在括号之外匹配单词边界。在括号内匹配退格键 (0x08)。
\\B 匹配非单词边界。
\\n, \\t, etc. 匹配换行符、回车符、制表符等。
\\Q 转义(引用)直到 \\E 的所有字符
\\E 结束由 \\Q 开始的引用

正则表达式示例

示例 描述
. 匹配除换行符之外的任何字符
[Rr]uby 匹配“Ruby”或“ruby”
rub[ye] 匹配“ruby”或“rube”
[aeiou] 匹配任何一个小写元音
[0-9] 匹配任何数字;与 [0123456789] 相同
[a-z] 匹配任何小写 ASCII 字母
[A-Z] 匹配任何大写 ASCII 字母
[a-zA-Z0-9] 匹配以上任何一个
[^aeiou] 匹配小写元音以外的任何内容
[^0-9] 匹配数字以外的任何内容
\\d 匹配一个数字:[0-9]
\\D 匹配一个非数字:[ ^0-9]
\\s 匹配一个空格字符:[ \t\r\n\f]
\\S 匹配非空格:[ ^ \t\r\n\f]
\\w 匹配单个单词字符:[A-Za-z0-9_]
\\W 匹配非单词字符:[ ^A-Za-z0-9_]
ruby? 匹配“rub”或“ruby”:y 可选
ruby* 匹配“rub”加上 0 个或多个 y
ruby+ 匹配“rub”加上 1 个或多个 y
\\d{3} 精确匹配 3 个数字
\\d{3,} 匹配 3 个或更多数字
\\d{3,5} 匹配 3、4 或 5 个数字
\\D\\d+ 无分组:+ 重复 \\d
(\\D\\d)+/ 分组:+ 重复 \\D\d 对
([Rr]uby(, )?)+ 匹配“Ruby”、“Ruby, ruby, ruby”等。

**注意** - 上述字符串中的每个反斜杠都出现两次。这是因为在 Java 和 Scala 中,单个反斜杠是字符串文字中的转义字符,而不是出现在字符串中的普通字符。因此,您需要编写“\\”而不是“\”才能在字符串中获得单个反斜杠。

尝试以下示例程序。

示例

import scala.util.matching.Regex

object Demo {
   def main(args: Array[String]) {
      val pattern = new Regex("abl[ae]\\d+")
      val str = "ablaw is able1 and cool"
      
      println((pattern findAllIn str).mkString(","))
   }
}

将上述程序保存为 **Demo.scala**。以下命令用于编译和执行此程序。

命令

\>scalac Demo.scala
\>scala Demo

输出

able1
广告