Go 语言正则表达式速查手册:30 分钟掌握核心语法与实战技巧
正则表达式在 Go 语言中的实现强大而灵活,但记不住所有语法怎么办?本文就是你的救星,适合收藏备查。
导入包
go
import "regexp"
- 包括编译、匹配、查找、替换等方法
regexp包底层使用高效自动机实现
编译正则
MustCompile
go
re := regexp.MustCompile(`\d+`)
- 快速编译正则表达式
- 编译失败时会 panic
Compile
go
re, err := regexp.Compile(`\d+`)
if err != nil {
log.Fatal(err)
}
- 安全编译正则表达式
- 返回
*Regexp和error
匹配
MatchString
go
matched, _ := regexp.MatchString(`\d+`, "123abc")
fmt.Println(matched) // true
- 检查字符串是否匹配正则
- 返回
bool和error
Match
go
re := regexp.MustCompile(`\d+`)
matched := re.Match([]byte("123abc"))
fmt.Println(matched) // true
- 检查字节切片是否匹配正则
- 返回
bool
查找
FindString
go
re := regexp.MustCompile(`\d+`)
result := re.FindString("123abc")
fmt.Println(result) // 123
- 查找第一个匹配的子字符串
- 返回
string
FindStringIndex
go
re := regexp.MustCompile(`\d+`)
result := re.FindStringIndex("123abc")
fmt.Println(result) // [0 3]
- 查找第一个匹配的子字符串的起止索引
- 返回
[]int
FindStringSubmatch
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.FindStringSubmatch("123abc")
fmt.Println(result) // [123abc 123 abc]
- 查找第一个匹配的子字符串及其子匹配
- 返回
[]string
FindStringSubmatchIndex
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.FindStringSubmatchIndex("123abc")
fmt.Println(result) // [0 6 0 3 3 6]
- 查找第一个匹配的子字符串及其子匹配的索引
- 返回
[]int
FindAllString
go
re := regexp.MustCompile(`\d+`)
result := re.FindAllString("123abc456", -1)
fmt.Println(result) // [123 456]
- 查找所有匹配的子字符串
- 第二个参数控制返回的匹配数量
FindAllStringIndex
go
re := regexp.MustCompile(`\d+`)
result := re.FindAllStringIndex("123abc456", -1)
fmt.Println(result) // [[0 3] [6 9]]
- 查找所有匹配的子字符串的起止索引
- 第二个参数控制返回的匹配数量
FindAllStringSubmatch
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.FindAllStringSubmatch("123abc456def", -1)
fmt.Println(result) // [[123abc 123 abc] [456def 456 def]]
- 查找所有匹配的子字符串及其子匹配
- 第二个参数控制返回的匹配数量
FindAllStringSubmatchIndex
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.FindAllStringSubmatchIndex("123abc456def", -1)
fmt.Println(result) // [[0 6 0 3 3 6] [6 12 6 9 9 12]]
- 查找所有匹配的子字符串及其子匹配的索引
- 第二个参数控制返回的匹配数量
替换
ReplaceAllString
go
re := regexp.MustCompile(`\d+`)
result := re.ReplaceAllString("123abc456", "NUM")
fmt.Println(result) // NUMabcNUM
- 替换所有匹配的子字符串
- 返回新的字符串
ReplaceAllStringFunc
go
re := regexp.MustCompile(`\d+`)
result := re.ReplaceAllStringFunc("123abc456", func(s string) string {
return strconv.Itoa(len(s))
})
fmt.Println(result) // 3abc3
- 使用函数替换所有匹配的子字符串
- 函数接收匹配的子字符串,返回替换后的字符串
ReplaceAllLiteralString
go
re := regexp.MustCompile(`\d+`)
result := re.ReplaceAllLiteralString("123abc456", "NUM")
fmt.Println(result) // NUMabcNUM
- 替换所有匹配的字面值子字符串
- 字面值替换不考虑元字符
分割
Split
go
re := regexp.MustCompile(`\d+`)
result := re.Split("123abc456def789", -1)
fmt.Println(result) // [ abc def ]
- 按正则表达式分割字符串
- 第二个参数控制分割次数
Fields
go
re := regexp.MustCompile(`\d+.*`)
result := re.Fields("123abc456def789")
fmt.Println(result) // [123abc456def789]
- 按正则表达式分割字符串,返回非空字段
- 适用于快速提取非空部分
匹配位置
FindSubmatchIndex
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.FindSubmatchIndex([]byte("123abc456def"))
fmt.Println(result) // [0 6 0 3 3 6]
- 查找第一个匹配的子匹配及其索引
- 返回
[]int
Match
go
re := regexp.MustCompile(`\d+`)
matched := re.Match([]byte("123abc"))
fmt.Println(matched) // true
- 检查字节切片是否匹配正则
- 返回
bool
匹配与替换高级用法
ReplaceAll
go
re := regexp.MustCompile(`\d+`)
result := re.ReplaceAll([]byte("123abc456"), []byte("NUM"))
fmt.Println(string(result)) // NUMabcNUM
- 替换所有匹配的字节切片
- 返回新的字节切片
Expand
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.Expand([]byte("Pre: Sub1: Post: Sub2"), []byte("123abc"), re.FindSubmatch([]byte("123abc")))
fmt.Println(string(result)) // Pre: 123: Post: abc
- 使用模板字符串扩展匹配结果
- 模板字符串中的
Sub1和Sub2被子匹配替换
ExpandString
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.ExpandString([]byte("Pre: Sub1: Post: Sub2"), "123abc", re.FindStringSubmatch("123abc"))
fmt.Println(string(result)) // Pre: 123: Post: abc
- 使用模板字符串扩展匹配结果
- 模板字符串中的
Sub1和Sub2被子匹配替换
正则表达式元字符
| 元字符 | 说明 |
|---------|----------------------|-----------------|
| . | 匹配任意字符(除换行符) |
| * | 匹配前面的字符 0 次或多次 |
| + | 匹配前面的字符 1 次或多次 |
| ? | 匹配前面的字符 0 次或 1 次 |
| ^ | 匹配字符串的开始 |
| $ | 匹配字符串的结束 |
| [] | 匹配字符集合中的任意一个字符 |
| - | 在字符集合中表示范围 |
| ` | ` | 逻辑或,匹配左边或右边的表达式 |
| () | 分组,捕获子匹配 |
| {m,n} | 匹配前面的字符至少 m 次,最多 n 次 |
常用正则表达式
邮箱校验
go
re := regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
result := re.MatchString("example@example.com")
fmt.Println(result) // true
- 常见邮箱格式校验
URL 校验
go
re := regexp.MustCompile(`^(http|https)://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$`)
result := re.MatchString("https://www.example.com")
fmt.Println(result) // true
- 常见 URL 格式校验
电话号码校验
go
re := regexp.MustCompile(`^\+?\d{10,15}$`)
result := re.MatchString("+1234567890")
fmt.Println(result) // true
- 国际电话号码校验
日期校验
go
re := regexp.MustCompile(`^\d{4}\-\d{2}\-\d{2}$`)
result := re.MatchString("2023-10-01")
fmt.Println(result) // true
- 标准日期格式校验
IP 地址校验
go
re := regexp.MustCompile(`^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`)
result := re.MatchString("192.168.1.1")
fmt.Println(result) // true
- 标准 IPv4 地址校验
正则表达式构造
转义
go
re := regexp.MustCompile(`\d\.\d{2}`) // 匹配 1.23
- 使用反斜杠
\转义特殊字符
字符集
go
re := regexp.MustCompile(`[a-z]`) // 匹配小写字母
- 使用
[]定义字符集
量词
| 量词 | 说明 |
|---|---|
* |
0 次或多次 |
+ |
1 次或多次 |
? |
0 次或 1 次 |
{n} |
恰好 n 次 |
{n,} |
至少 n 次 |
{n,m} |
至少 n 次,最多 m 次 |
分组与捕获
go
re := regexp.MustCompile(`(\d+)(\w+)`)
result := re.FindStringSubmatch("123abc")
fmt.Println(result) // [123abc 123 abc]
- 使用
()分组,捕获子匹配
非捕获分组
go
re := regexp.MustCompile(`(?:\d+)(\w+)`)
result := re.FindStringSubmatch("123abc")
fmt.Println(result) // [123abc abc]
- 使用
(?:...)创建非捕获分组
前瞻与后瞻
| 运算符 | 说明 |
|---|---|
(?=...) |
正向前瞻,匹配后跟指定模式的字符串 |
(?!=...) |
负向前瞻,匹配不后跟指定模式的字符串 |
(?<=...) |
正向后瞻,匹配前有指定模式的字符串 |
(?<!...) |
负向后瞻,匹配前没有指定模式的字符串 |
示例
go
re := regexp.MustCompile(`\d+(?=px)`)
result := re.FindString("width: 123px")
fmt.Println(result) // 123
- 使用正向前瞻匹配
px前的数字
正则表达式性能优化
预编译
go
var re = regexp.MustCompile(`\d+`)
- 预编译正则表达式,提高性能
非捕获分组
go
re := regexp.MustCompile(`(?:\d+)(\w+)`)
- 减少捕获分组,提高性能
限制量词
go
re := regexp.MustCompile(`\d{1,4}`)
- 限制量词范围,避免过度匹配
避免使用回溯
go
re := regexp.MustCompile(`^\d+.*\d+$`)
- 使用非贪婪匹配或前瞻/后瞻,减少回溯
实战技巧
提取所有邮箱
go
re := regexp.MustCompile(`[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}`)
result := re.FindAllString("email@example.com, other@example.net", -1)
fmt.Println(result) // [email@example.com other@example.net]
- 从文本中提取所有邮箱地址
替换敏感信息
go
re := regexp.MustCompile(`\d{16}`)
result := re.ReplaceAllString("Credit card: 1234567890123456", "XXXX")
fmt.Println(result) // Credit card: XXXX
- 替换信用卡号等敏感信息
检查用户名
go
re := regexp.MustCompile(`^[a-zA-Z0-9]{3,16}$`)
result := re.MatchString("user123")
fmt.Println(result) // true
- 检查用户名是否符合 3-16 位的字母数字规则
处理复杂日志
go
re := regexp.MustCompile(`(?P<date>\d{4}\-\d{2}\-\d{2})\s(?P<time>\d{2}:\d{2}:\d{2})\s(?P<level>\w+)\s(?P<message>.*)`)
logLine := "2023-10-01 12:34:56 INFO Log message here"
result := re.FindStringSubmatch(logLine)
for i, name := range re.SubexpNames() {
if i != 0 && name != "" {
fmt.Printf("%s: %s\n", name, result[i])
}
}
- 提取日志中的日期、时间、级别和消息
推荐工具
在处理正则表达式时,Hey Cron 是一个免费在线工具网站,提供多种实用工具,包括:
- 正则表达式生成器:中文描述秒转正则,快速生成复杂正则表达式
- JSON 格式化:轻松格式化和验证 JSON 数据
- Base64 编码解码:快速编码和解码 Base64 字符串
- 时间戳转换:方便地在时间戳和日期时间之间转换
- JWT 解析:解析 JSON Web Token,查看其内容
无论是开发还是调试,Hey Cron 都能提高你的效率。立即访问 Hey Cron 试试吧!