Scala正则表达式用法

概述

记录一下Scala中关于正则表达式的一些方法的使用,之前用惯了Python,发现差别还是挺大的。。。

基本函数/方法使用

正则表达式定义

1
2
val pattern = "\\d+".r
// 类似于python中的 pattern = re.compile("\d+")

还有另一种定义方式,可以为每个分组指定名称,在使用scala.util.matching.Regex.Match对象时使用(下文介绍)

1
val pattern = "(\\d+)-(\\d+)-(\\d+)".r("year", "month", "day")

各种函数

findFirstIn vs findFirstMatchIn

这两个函数都用于查找匹配上的第一个元素,区别在于返回值,findFirstIn返回:Option[String], findFirstMatchIn返回:Option[Match]

1
2
3
4
val pattern = "\\d+".r
val text = "2020-04-16"
//output => 2020
println(pattern.findFirstIn(text).get)

findAllIn vs findAllMatchIn

这两个函数都用于查找匹配上的全部元素

1
2
3
4
val pattern = "\\d+".r
val text = "2020-04-16"
//output => List(2020, 04, 16)
println(pattern.findAllIn(text).toList)

findPrefixOf vs findPrefixMatchOf

此函数用于从目标字符串开始位置开始匹配,若匹配上则返回匹配到的值,发偶咋返回None,类似Pyhton的 re.match

1
2
3
4
val pattern = "\\d+".r
val text = "2020-04-16"
//output => 2020
println(pattern.findPrefixOf(text).get)

replaceFirstIn vs replaceAllIn vs replaceSomeIn

这几个函数的作用是替换,类似python的re.sub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
val pattern = "\\d+".r
val text = "2020-01-01"
// output => xxx-01-01
println(pattern.replaceFirstIn(text, "xxx").get)
// output => xxx-xxx-xxx
println(pattern.replaceAllIn(text, "xxx").get)
// 根据匹配到的对象自定义函数去进行不同的替换
// output => year-xxx-xxx
val replace_f = (m: Match) => {
var r = Option("")
m.group(1) match {
case "2020" => r = Some("year")
case _ => r = Some("xxx")
}
r
}
println(pattern.replaceSomeIn(text, replace_f))

关于scala.util.matching.Regex.Match

细节参见文档。简单用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
val pattern = "(\\d+)".r("year")
val text = "2020-01-01"
val _match = pattern.findFirstMatchIn(text).get
// 匹配到的文本 output => 2020
println(_match.source)
// 匹配的起始位置 output => 0
println(_match.start)
// 匹配的分组 output => 2020
println(_match.group(0))
// 匹配的分组 output => 2020
println(_match.group("year"))

一些不太习惯的地方

#1

我以为会是: 2020

1
2
3
4
5
val text = "Hello, I am Scala Regex. date:2020-01-01"
val pattern = "date:(\\d+)".r

// output => date:2020
println(pattern.findFirstIn(text).get)

所以当你想获取2020时,可以这么写

1
println(pattern.findFirstMatchIn(text).get.group(1))

#2

总感觉这个语法很诡异。。。

1
2
3
4
5
6
val text = "Hello, I am Scala Regex. date:2020-01-01"
val pattern = ".*date:(\\d+).*".r

val pattern(year) = text
// output => 2020
println(year)