8.11 Go语言正则表达式:regexp包 - Go语言中文社区

8.11 Go语言正则表达式:regexp包


正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具。虽然正则表达式比纯粹的文本匹配效率低,但是它却更灵活,按照它的语法规则,根据需求构造出的正则表达式能够从原始文本中筛选出几乎任何你想要得到的字符组合。

Go语言通过 regexp 包为正则表达式提供了官方支持,其采用 RE2 语法,除了\c、\C外,Go语言和 Perl、Python 等语言的正则基本一致。

正则表达式语法规则

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为”元字符”)构成的文字序列,可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。

下面的表格中列举了构成正则表达式的一些语法规则及其含义。

1) 字符
语法 说明 表达式示例 匹配结果
一般字符 匹配自身 abc abc
. 匹配任意除换行符”\n”外的字符, 在 DOTALL 模式中也能匹配换行符 a.c abc
\d 数字:[0-9] a\dc a1c
\D 非数字:[^\d] a\Dc abc
\s 空白字符:[<空格>\t\r\n\f\v] a\sc a c
\S 非空白字符:[^\s] a\Sc abc
\w 单词字符:[A-Za-z0-9] a\wc abc
\W 非单词字符:[^\w] a\Wc a c
2) 数量词(用在字符或 (…) 之后)
语法 说明 表达式示例 匹配结果
* 匹配前一个字符 0 或无限次 abc* ab 或 abccc
+ 匹配前一个字符 1 次或无限次 abc+ abc 或 abccc
? 匹配前一个字符 0 次或 1 次 abc? ab 或 abc
{m} 匹配前一个字符 m 次 ab{2}c abbc
{m,n} 匹配前一个字符 m 至 n 次,m 和 n 可以省略,若省略 m,则匹配 0 至 n 次;若省略 n,则匹配 m 至无限次 ab{1,2}c abc 或 abbc
3) 边界匹配
语法 说明 表达式示例 匹配结果
^ 匹配字符串开头,在多行模式中匹配每一行的开头 ^abc abc
$ 匹配字符串末尾,在多行模式中匹配每一行的末尾 abc$ abc
\A 仅匹配字符串开头 \Aabc abc
\Z 仅匹配字符串末尾 abc\Z abc
\b 匹配 \w 和 \W 之间 a\b!bc a!bc
\B [^\b] a\Bbc abc
5) 特殊构造(不作为分组)
语法 说明 表达式示例 匹配结果
(?:…) (…) 的不分组版本,用于使用 “ “ 或后接数量词 (?:abc){2} abcabc
(?iLmsux) iLmsux 中的每个字符代表一种匹配模式,只能用在正则表达式的开头,可选多个 (?i)abc AbC
(?#…) # 后的内容将作为注释被忽略。 abc(?#comment)123 abc123
(?=…) 之后的字符串内容需要匹配表达式才能成功匹配 a(?=\d) 后面是数字的 a
(?!…) 之后的字符串内容需要不匹配表达式才能成功匹配 a(?!\d) 后面不是数字的 a
(?<=…) 之前的字符串内容需要匹配表达式才能成功匹配 (?<=\d)a 前面是数字的a
(?<!…) 之前的字符串内容需要不匹配表达式才能成功匹配 (?<!\d)a 前面不是数字的a

Regexp 包的使用

下面通过几个示例来演示一下 regexp 包的使用。

【示例 1】匹配指定类型的字符串。

  1. package main
  2. import (
  3. "fmt"
  4. "regexp"
  5. )
  6. func main() {
  7. buf := "abc azc a7c aac 888 a9c tac"
  8. //解析正则表达式,如果成功返回解释器
  9. reg1 := regexp.MustCompile(`a.c`)
  10. if reg1 == nil {
  11. fmt.Println("regexp err")
  12. return
  13. }
  14. //根据规则提取关键信息
  15. result1 := reg1.FindAllStringSubmatch(buf, -1)
  16. fmt.Println("result1 = ", result1)
  17. }

运行结果如下:

result1 = [[abc] [azc] [a7c] [aac] [a9c]]  

【示例 2】匹配 a 和 c 中间包含一个数字的字符串。

  1. package main
  2. import (
  3. "fmt"
  4. "regexp"
  5. )
  6. func main() {
  7. buf := "abc azc a7c aac 888 a9c tac"
  8. //解析正则表达式,如果成功返回解释器
  9. reg1 := regexp.MustCompile(`a[0-9]c`)
  10. if reg1 == nil { //解释失败,返回nil
  11. fmt.Println("regexp err")
  12. return
  13. }
  14. //根据规则提取关键信息
  15. result1 := reg1.FindAllStringSubmatch(buf, -1)
  16. fmt.Println("result1 = ", result1)
  17. }

运行结果如下:

result1 = [[a7c] [a9c]]

【示例 3】使用 \d 来匹配 a 和 c 中间包含一个数字的字符串。

  1. package main
  2. import (
  3. "fmt"
  4. "regexp"
  5. )
  6. func main() {
  7. buf := "abc azc a7c aac 888 a9c tac"
  8. //解析正则表达式,如果成功返回解释器
  9. reg1 := regexp.MustCompile(`a\dc`)
  10. if reg1 == nil { //解释失败,返回nil
  11. fmt.Println("regexp err")
  12. return
  13. }
  14. //根据规则提取关键信息
  15. result1 := reg1.FindAllStringSubmatch(buf, -1)
  16. fmt.Println("result1 = ", result1)
  17. }

运行结果如下:

result1 = [[a7c] [a9c]]

【示例 4】匹配字符串中的小数。

  1. package main
  2. import (
  3. "fmt"
  4. "regexp"
  5. )
  6. func main() {
  7. buf := "43.14 567 agsdg 1.23 7. 8.9 1sdljgl 6.66 7.8 "
  8. //解释正则表达式
  9. reg := regexp.MustCompile(`\d+\.\d+`)
  10. if reg == nil {
  11. fmt.Println("MustCompile err")
  12. return
  13. }
  14. //提取关键信息
  15. //result := reg.FindAllString(buf, -1)
  16. result := reg.FindAllStringSubmatch(buf, -1)
  17. fmt.Println("result = ", result)
  18. }

运行结果如下:

result = [[43.14] [1.23] [8.9] [6.66] [7.8]]

【示例 5】匹配 div 标签中的内容。

  1. package main
  2. import (
  3. "fmt"
  4. "regexp"
  5. )
  6. func main() {
  7. // 原生字符串
  8. buf := `
  9. <!DOCTYPE html>
  10. <html lang="zh-CN">
  11. <head>
  12. <title>Go语言中文社区 | Go语言入门教程</title>
  13. </head>
  14. <body>
  15. <div>Go语言简介</div>
  16. <div>Go语言基本语法
  17. Go语言变量的声明
  18. Go语言教程简明版
  19. </div>
  20. <div>Go语言容器</div>
  21. <div>Go语言函数</div>
  22. </body>
  23. </html>
  24. `
  25. //解释正则表达式
  26. reg := regexp.MustCompile(`<div>(?s:(.*?))</div>`)
  27. if reg == nil {
  28. fmt.Println("MustCompile err")
  29. return
  30. }
  31. //提取关键信息
  32. result := reg.FindAllStringSubmatch(buf, -1)
  33. //过滤<></>
  34. for _, text := range result {
  35. fmt.Println("text[1] = ", text[1])
  36. }
  37. }

运行结果如下:

  • text[1] = Go语言简介
  • text[1] = Go语言基本语法
  • Go语言变量的声明
  • Go语言教程简明版
  • text[1] = Go语言容器
  • text[1] = Go语言函数

【示例 6】通过 Compile 方法返回一个 Regexp 对象,实现匹配,查找,替换相关的功能。

  1. package main
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strconv"
  6. )
  7. func main() {
  8. //目标字符串
  9. searchIn := "John: 2578.34 William: 4567.23 Steve: 5632.18"
  10. pat := "[0-9]+.[0-9]+" //正则
  11. f := func(s string) string{
  12. v, _ := strconv.ParseFloat(s, 32)
  13. return strconv.FormatFloat(v * 2, 'f', 2, 32)
  14. }
  15. if ok, _ := regexp.Match(pat, []byte(searchIn)); ok {
  16. fmt.Println("Match Found!")
  17. }
  18. re, _ := regexp.Compile(pat)
  19. //将匹配到的部分替换为 "##.#"
  20. str := re.ReplaceAllString(searchIn, "##.#")
  21. fmt.Println(str)
  22. //参数为函数时
  23. str2 := re.ReplaceAllStringFunc(searchIn, f)
  24. fmt.Println(str2)
  25. }

输出结果:

  • Match Found!
  • John: ##.# William: ##.# Steve: ##.#
  • John: 5156.68 William: 9134.46 Steve: 11264.36

上面代码中 Compile 方法可以解析并返回一个正则表达式,如果成功返回,则说明该正则表达式正确可用于匹配文本。

另外我们也可以使用 MustCompile 方法,它也可以像 Compile 方法一样检验正则的有效性,但是当正则不合法时程序将 panic。

版权声明:本教程内容除了本站原创内容外,还有来源自C语言编程网,博客园,CSDN等技术站点,感谢相关博主原创文章,转载请附上原文出处链接和本声明。
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 阅读 ( 612 )
  • 分类:Go

0 条评论

官方社群

GO教程

猜你喜欢