Go 语言的 regexp 包提供了对正则表达式的支持。
正则表达式(regex)是一种字符串搜索模式,用来检查一个字符串是否符合某种特定的模式,或从中提取符合某种模式的子字符串。
regexp 包支持对字符串的匹配、搜索和替换。它基于 RE2 正则表达式引擎,性能优异,避免了回溯带来的性能瓶颈。
该包提供了多个函数来编译正则表达式并进行匹配、查找、替换等操作。
该函数用于编译正则表达式字符串 pattern,并返回一个 Regexp 类型对象。如果正则表达式无效,会返回一个错误。
示例:
1 2 3 4 5 |
r, err := regexp.Compile(`\d+`) // 匹配一个或多个数字 if err != nil { fmt.Println("Error compiling regex:", err) return } |
该函数与 Compile 类似,不过如果正则表达式不合法,它会立即 panic。适合在启动时使用,确保正则表达式是合法的。
示例:
1 |
r := regexp.MustCompile(`\d+`) |
该方法检查给定的字符串 s 是否匹配正则表达式。如果匹配,返回 true,否则返回 false。
示例:
1 2 3 |
r := regexp.MustCompile(`\d+`) fmt.Println(r.MatchString("12345")) // 输出:true fmt.Println(r.MatchString("abc")) // 输出:false |
该方法查找字符串中第一个匹配正则表达式的子字符串并返回。如果没有找到匹配项,则返回空字符串。
示例:
1 2 |
r := regexp.MustCompile(`\d+`) fmt.Println(r.FindString("abc 12345 xyz")) // 输出:12345 |
查找字符串中所有匹配正则表达式的子字符串,并返回一个字符串切片。如果 n 为 -1,则表示返回所有匹配的子串。
示例:
1 2 |
r := regexp.MustCompile(`\d+`) fmt.Println(r.FindAllString("abc 123 4567 89", -1)) // 输出:[123 4567 89] |
该方法用于替换字符串中所有匹配正则表达式的子字符串。repl 是替换的文本。
示例:
1 2 3 |
r := regexp.MustCompile(`\d+`) result := r.ReplaceAllString("abc 123 4567 xyz", "#") fmt.Println(result) // 输出:abc # # xyz |
查找第一个匹配的子字符串,并返回每个捕获组的内容(包括完整匹配)。返回的是一个二维字节切片,每个字节切片表示一个匹配项。
示例:
1 2 3 |
r := regexp.MustCompile(`(\d+)-(\d+)`) match := r.FindSubmatch([]byte("abc 123-4567")) fmt.Println(match) // 输出:[[123-4567 123 4567]] |
根据正则表达式分割字符串,返回一个字符串切片。n 参数表示最多分割的次数。
示例:
1 2 |
r := regexp.MustCompile(`\s+`) fmt.Println(r.Split("this is a test", -1)) // 输出:[this is a test] |
Go 语言的 regexp 包使用的是 RE2 正则表达式引擎,它支持一些常见的正则表达式语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package main
import ( "fmt" "regexp" )
func main() { // 编译正则表达式 r := regexp.MustCompile(`\d+`) // 检查字符串是否包含数字 fmt.Println(r.MatchString("abc123")) // 输出:true fmt.Println(r.MatchString("abc")) // 输出:false } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package main
import ( "fmt" "regexp" )
func main() { // 编译正则表达式 r := regexp.MustCompile(`\d+`) // 查找字符串中的第一个数字 result := r.FindString("abc 12345 xyz") fmt.Println(result) // 输出:12345 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package main
import ( "fmt" "regexp" )
func main() { // 编译正则表达式 r := regexp.MustCompile(`\d+`) // 替换数字为 # result := r.ReplaceAllString("abc 123 4567 xyz", "#") fmt.Println(result) // 输出:abc # # xyz } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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] } |
regexp 包是 Go 语言中一个强大的工具,用于进行字符串模式匹配和替换操作。
通过使用该包,你可以灵活地处理复杂的字符串匹配任务,并且可以高效地进行文本处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
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 } |