大家知道正则表达式^
是用来匹配行首,$
是用来匹配行尾。如果是多行全局的情况,就会分别匹配每一行。比如一个匹配 QQ 邮箱的正则^\d+@qq\.com$
,用 regex101 测试的结果:

而在 Go 里面如果要启用多行匹配一般是这样写:
1
|
re := regexp.MustCompile(`(?m)^\d+@qq\.com$`)
|
这里的(?m)
就是多行匹配的意思。
全局匹配在其他语言中是一般会用 g 表示,而在 Go 中应该调用带 All 的方法,比如 FindAllString。
但是 Go 的多行全局匹配时其实对换行符有要求,不会匹配 CRLF(\r\n,Windows 中的换行)和 CR(\r,macOS 中的换行)的,只会匹配 LF(\n,Linux 中的换行)。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package main
import (
"log/slog"
"regexp"
)
func main() {
str1 := "156161656@qq.com\r\n51381651@qq.com\r\n1115258262@qq.com"
str2 := "156161656@qq.com\n51381651@qq.com\n1115258262@qq.com"
str3 := "156161656@qq.com\r51381651@qq.com\r1115258262@qq.com"
re := regexp.MustCompile(`(?m)^\d+@qq\.com$`)
slog.Info("str1", "matched", re.FindAllString(str1, -1))
slog.Info("str2", "matched", re.FindAllString(str2, -1))
slog.Info("str2", "matched", re.FindAllString(str3, -1))
}
|
输出:
1
2
3
|
2024/10/05 20:39:16 INFO str1 matched=[1115258262@qq.com]
2024/10/05 20:39:16 INFO str2 matched="[156161656@qq.com 51381651@qq.com 1115258262@qq.com]"
2024/10/05 20:39:16 INFO str2 matched=[]
|
可以看到只有 str2 是正确匹配的。str1 由于最后一个邮箱后面没有\r\n,也作为字符串的结尾被匹配了。
如果是读文件的情况,可能 Windows 上的文件本来就是\r\n换行的,目前没有找到什么好的办法,只能用 strings.ReplaceAll 把\r全部都替换掉。
Rust 的正则库似乎也有这个问题:https://github.com/rust-lang/regex/issues/244