当前位置: 首页 > article >正文

【go语言】regexp包,正则表达式

Go语言 regexp 包详解

Go 语言的 regexp 包提供了对正则表达式的支持。
正则表达式(regex)是一种字符串搜索模式,用来检查一个字符串是否符合某种特定的模式,或从中提取符合某种模式的子字符串。

1. regexp 包概述

regexp 包支持对字符串的匹配、搜索和替换。它基于 RE2 正则表达式引擎,性能优异,避免了回溯带来的性能瓶颈。
该包提供了多个函数来编译正则表达式并进行匹配、查找、替换等操作。

2. 常用函数

2.1 regexp.Compile(pattern string) (*Regexp, error)

该函数用于编译正则表达式字符串 pattern,并返回一个 Regexp 类型对象。如果正则表达式无效,会返回一个错误。
示例:

r, err := regexp.Compile(`\d+`)  // 匹配一个或多个数字
if err != nil {
    fmt.Println("Error compiling regex:", err)
    return
}

2.2 regexp.MustCompile(pattern string) *Regexp

该函数与 Compile 类似,不过如果正则表达式不合法,它会立即 panic。适合在启动时使用,确保正则表达式是合法的。
示例:

r := regexp.MustCompile(`\d+`)

2.3 r.MatchString(s string) bool

该方法检查给定的字符串 s 是否匹配正则表达式。如果匹配,返回 true,否则返回 false
示例:

r := regexp.MustCompile(`\d+`)
fmt.Println(r.MatchString("12345"))  // 输出:true
fmt.Println(r.MatchString("abc"))    // 输出:false

2.4 r.FindString(s string) string

该方法查找字符串中第一个匹配正则表达式的子字符串并返回。如果没有找到匹配项,则返回空字符串。
示例:

r := regexp.MustCompile(`\d+`)
fmt.Println(r.FindString("abc 12345 xyz")) // 输出:12345

2.5 r.FindAllString(s string, n int) []string

查找字符串中所有匹配正则表达式的子字符串,并返回一个字符串切片。如果 n 为 -1,则表示返回所有匹配的子串。
示例:

r := regexp.MustCompile(`\d+`)
fmt.Println(r.FindAllString("abc 123 4567 89", -1))  // 输出:[123 4567 89]

2.6 r.ReplaceAllString(s string, repl string) string

该方法用于替换字符串中所有匹配正则表达式的子字符串。repl 是替换的文本。
示例:

r := regexp.MustCompile(`\d+`)
result := r.ReplaceAllString("abc 123 4567 xyz", "#")
fmt.Println(result) // 输出:abc # # xyz

2.7 r.FindSubmatch(s string) [][]byte

查找第一个匹配的子字符串,并返回每个捕获组的内容(包括完整匹配)。返回的是一个二维字节切片,每个字节切片表示一个匹配项。
示例:

r := regexp.MustCompile(`(\d+)-(\d+)`)
match := r.FindSubmatch([]byte("abc 123-4567"))
fmt.Println(match)  // 输出:[[123-4567 123 4567]]

2.8 r.Split(s string, n int) []string

根据正则表达式分割字符串,返回一个字符串切片。n 参数表示最多分割的次数。
示例:

r := regexp.MustCompile(`\s+`)
fmt.Println(r.Split("this is a test", -1))  // 输出:[this is a test]

3. 正则表达式语法

Go 语言的 regexp 包使用的是 RE2 正则表达式引擎,它支持一些常见的正则表达式语法:

  • .:匹配除换行符以外的任何单个字符。
  • ^:匹配输入字符串的开始位置。
  • $:匹配输入字符串的结束位置。
  • *:匹配前一个字符零次或多次。
  • +:匹配前一个字符一次或多次。
  • ?:匹配前一个字符零次或一次。
  • {n,m}:匹配前一个字符至少 n 次,但不超过 m 次。
  • |:匹配左侧或右侧的表达式。
  • ():分组,括起来的部分作为一个整体进行匹配。
  • []:字符集,匹配括号内的任何一个字符。
  • \d:匹配一个数字,等同于 [0-9]
  • \w:匹配一个字母或数字字符,等同于 [a-zA-Z0-9_]
  • \s:匹配一个空白字符(包括空格、制表符、换行符等)。

4. 示例

示例 1:检查字符串是否符合正则表达式

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// 编译正则表达式
	r := regexp.MustCompile(`\d+`)
	// 检查字符串是否包含数字
	fmt.Println(r.MatchString("abc123"))  // 输出:true
	fmt.Println(r.MatchString("abc"))     // 输出:false
}

示例 2:提取数字

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// 编译正则表达式
	r := regexp.MustCompile(`\d+`)
	// 查找字符串中的第一个数字
	result := r.FindString("abc 12345 xyz")
	fmt.Println(result)  // 输出:12345
}

示例 3:替换字符串中的数字

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// 编译正则表达式
	r := regexp.MustCompile(`\d+`)
	// 替换数字为 #
	result := r.ReplaceAllString("abc 123 4567 xyz", "#")
	fmt.Println(result)  // 输出:abc # # xyz
}

示例 4:分割字符串

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// 编译正则表达式
	r := regexp.MustCompile(`\s+`)
	// 按空白字符分割字符串
	result := r.Split("this is a test", -1)
	fmt.Println(result)  // 输出:[this is a test]
}

5. 性能与注意事项

  • Go 的 regexp 包非常高效,特别是在处理大数据量时,RE2 正则表达式引擎避免了回溯带来的性能问题。
  • 使用正则表达式时需要谨慎,以避免过度复杂的模式导致性能瓶颈。

总结

regexp 包是 Go 语言中一个强大的工具,用于进行字符串模式匹配和替换操作。
通过使用该包,你可以灵活地处理复杂的字符串匹配任务,并且可以高效地进行文本处理。


案例

package _case

import (
	"fmt"
	"regexp"
)

func RegexpCase() {
	test1()
	fmt.Println("------------")
	test2()
}

func test2() {
	// 案例
	pattern := `^[a-z]+\[[0-9]+\]$`
	re := regexp.MustCompile(pattern)
	fmt.Println(re.MatchString("asdf[22114]"))

	// FindAll传入[]byte;
	// FindAllString传入string
	bytes := re.FindAll([]byte("haha[1234]"), -1)
	fmt.Println(string(bytes[0]))

	re = regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
	str := "今天日期:2024-10-21"
	replaced := re.ReplaceAllString(str, "我日你妈的")
	fmt.Println(replaced)
}

// 常见的正则表达式字符及其含义
// 锚点字符:
//
// ^:匹配字符串的开始。例如,^abc 匹配以 "abc" 开头的字符串。
// $:匹配字符串的结束。例如,abc$ 匹配以 "abc" 结尾的字符串。
// 字符匹配:
//
// .(点号):匹配任意一个字符,除了换行符。例子:a.b 可以匹配 "a_b"、"a1b",但不能匹配 "ab"。
// [ ]:定义字符集合,匹配集合中的任意一个字符。例如,[abc] 匹配 "a"、"b" 或 "c"。
// [^ ]:排除字符集合,匹配集合外的任意字符。例如,[^abc] 匹配除 "a"、"b" 和 "c" 以外的任意字符。
// 量词:
//
// *:匹配前面的元素 0 次或多次。例如,a* 匹配空字符串、"a"、"aa" 等。
// +:匹配前面的元素 1 次或多次。例如,a+ 匹配 "a"、"aa"、"aaa" 等。
// ?:匹配前面的元素 0 次或 1 次。例如,a? 匹配空字符串或 "a"。
// {n}:匹配前面的元素恰好 n 次。例如,a{3} 匹配 "aaa"。
// {n,}:匹配前面的元素至少 n 次。例如,a{2,} 匹配 "aa"、"aaa"、"aaaa" 等。
// {n,m}:匹配前面的元素至少 n 次,但不超过 m 次。例如,a{2,4} 匹配 "aa"、"aaa" 或 "aaaa"。
// 字符类:
//
// \d:匹配任意数字,等同于 [0-9]。
// \D:匹配非数字字符,等同于 [^0-9]。
// \w:匹配字母、数字或下划线,等同于 [a-zA-Z0-9_]。
// \W:匹配非字母、数字或下划线字符,等同于 [^a-zA-Z0-9_]。
// \s:匹配任意空白字符(包括空格、制表符、换行符等)。
// \S:匹配任意非空白字符。
// 分组和选择:
//
// ( ):定义捕获组,匹配的内容可以在后续操作中引用。例如,(abc) 匹配 "abc"。
// |:逻辑或,表示左右两边任意一个匹配即可。例如,a|b 匹配 "a" 或 "b"。
// 反斜杠转义:
//
// \:反斜杠用于转义特殊字符。例如,\. 匹配字符 ".",而不是表示任意字符的点号。
// 特殊字符类:
//
// \b:匹配单词边界。例如,\bword\b 匹配完整的 "word",但不会匹配 "sword" 中的 "word"。
// \B:匹配非单词边界。
// 举例说明
// ^\d{3}-\d{2}-\d{4}$:匹配符合格式的社会保障号(比如 "123-45-6789")。
//
// ^:匹配字符串的开始。
// \d{3}:匹配 3 个数字。
// -:匹配字符 -。
// \d{2}:匹配 2 个数字。
// \d{4}:匹配 4 个数字。
// $:匹配字符串的结束。
// ([A-Z][a-z]+):匹配以大写字母开头的单词(如 "Apple")。
//
// [A-Z]:匹配一个大写字母。
// [a-z]+:匹配一个或多个小写字母。
// ( ):定义捕获组。
func test1() {
	// Compile解析并返回一个正则表达式。如果成功返回,该Regexp就可用于匹配文本。
	re := regexp.MustCompile(".com")
	// FindString
	fmt.Println(re.FindString("(cainiao.com)"))
	fmt.Println(re.FindString("(cainiao.dz)"))
	fmt.Println(re.FindString("(cainiao1.com1)"))

	// FindStringIndex return符合正则表达式的字符的索引,左闭右开
	fmt.Println(re.FindStringIndex("google.com"))
	fmt.Println(re.FindStringIndex("abc.org"))
	fmt.Println(re.FindStringIndex("fb.com"))

	// FindStringSubmatch 该方法返回具有最左边匹配项和匹配组的字符串。找不到返回空字符串
	// ([a-z]+)称为匹配组
	re1 := regexp.MustCompile("f([a-z]+)ing")
	re2 := regexp.MustCompile("f([a-z]+)ing")
	fmt.Println(re1.FindStringSubmatch("flying1"))
	fmt.Println(re1.FindStringSubmatch("abcfloatingxyz"))
	fmt.Println(re2.FindStringSubmatch("flying1"))
	fmt.Println(re2.FindStringSubmatch("abcfloatingxyz"))

	fmt.Println("-----------")
	pattern := "([a-z]+)"
	regex := regexp.MustCompile(pattern)
	// FindStringSubmatch 只会返回一个 包含的匹配结果,和一个 匹配组 合成的一个切片
	// len:2
	matches := regex.FindStringSubmatch("apple banana orange")
	fmt.Println(matches[0])
	fmt.Println(matches[1])
	//fmt.Println(matches[2])
	//fmt.Println(matches[3])
	// 如果想要匹配所有符合正则表达式的值,要用FindAllStringSubmatch
	// n为-1时,匹配所有符合条件的字符串,n不为-1时,表示只匹配n次
	// 会返回一个二维切片
	matches1 := regex.FindAllStringSubmatch("apple banana orange", -1)
	fmt.Println(matches1)
	// 遍历匹配结果
	for i, match := range matches1 {
		fmt.Printf("匹配 %d 结果:%s\n", i, match[0])
		fmt.Printf("捕获组 %d 结果:%s\n", i, match[1])
	}

	// 命名捕获组语法
	// (?P<name>pattern)
	// name:捕获组名称,pattern:捕获组模式
	pattern = "(?P<fruit>[a-z]+)"
	// 建立正则表达式
	re3 := regexp.MustCompile(pattern)
	// 匹配单个值
	matches = re3.FindStringSubmatch("apple banana orange")
	fruit := matches[re3.SubexpIndex("fruit")]
	fmt.Println(fruit)
	// 匹配多个值
	matches1 = re3.FindAllStringSubmatch("apple banana orange", -1)
	for i, match := range matches1 {
		fruit = match[re3.SubexpIndex("fruit")]
		fmt.Printf("匹配结果%d:%s\n", i, match[0])
		fmt.Printf("捕获组组%d:%s\n", i, fruit)
	}

	// regexp.Match() 判断在[]byte中能否找到给定正则表达式的值,返回bool和err
	// .*:表示任意数量的任意字符(包括 0 个字符),可以匹配任何字符,除了换行符
	// "^abc.*z$"含义:
	// 匹配以abc开头中间任意个数任意类型字符(除换行符外)以z结尾的字符串
	matched, err := regexp.Match("^abc.*z$", []byte("abcdeeffgz"))
	fmt.Println(matched, err)
	matched, err = regexp.Match("^abc.*z$", []byte("bcdefgz"))
	fmt.Println(matched, err)

	// regexp.MatchString()类似regexp.Match()不过他只传字符串,而Match只传[]byte
}


http://www.kler.cn/a/444502.html

相关文章:

  • 解决新版本Spring中lombok失效的问题
  • 与运动序列学习相关的眼动功能连接
  • Docker监控新纪元:Prometheus引领高效容器监控革命
  • 从零开始:PHP基础教程系列-第12篇:数据库基础与PDO使用
  • 魏裕雄的JAVA学习总结
  • SQL 多表查询实战:使用 WHERE 实现表关联
  • 深入了解V-model实现数据双向绑定
  • pdf操作组件aspose的无限制使用方法
  • Moretl开箱即用日志采集
  • 探索 Bokeh:轻松创建交互式数据可视化的强大工具
  • useContext Hook 的使用及规范
  • ASP.NET Core+EF Core+Vue.js/Ant Design/Axios 实现简单的图书查询
  • 浅谈OA和门户网站的区别
  • 语言模型 F5-E2 TTS:音色 情绪一键克隆,轻松实现多角色对话
  • 二分法(总体概述)
  • Linux下部署MySQL8.0集群 - 主从复制(一主两从)
  • 前后端跨域问题(CROS)
  • shell命令查看在用端口
  • 【图像分类实用脚本】数据可视化以及高数量类别截断
  • Unity 在不同分辨率的屏幕设备中保持特定的纵横比