Go语言正则表达式的使用详解
来源:脚本之家
时间:2022-12-28 18:31:56 292浏览 收藏
来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《Go语言正则表达式的使用详解》,介绍一下正则表达式,希望对大家的知识积累有所帮助,助力实战开发!
正则表达式是一种进行模式匹配和文本操纵的功能强大的工具。正则表达式灵活、易用,按照它的语法规则,随需构造出的匹配模式就能够从原始文本中筛选出几乎任何你想要得到的字符组合。
准则
- 默认是最短匹配,只要字符串满足条件就返回。
- 如果没有匹配到,都是返回为nil。
- 如果需要做最长匹配,调用Longest()函数。
- 正则表达式功能:匹配(macth),查找(find)和替换(replace)。
- 存在长度选择的函数,传入
使用regexp调用
Match,MatchReader和 MatchString
// 判断b中是够包含pattern能够组成的任意字符串 func Match(pattern string, b []byte) (matched bool, err error) // 判断reader r中返回的字符串是否包含pattern能够组成的任意字符串 func MatchReader(pattern string, r io.RuneReader) (matched bool, err error) // 判断字符串s中是否包含pattern能够组成的任意字符串 func MatchString(pattern string, s string) (matched bool, err error)
Compile 和 MushCompile
func Compile(expr string) (*Regexp, error)
func MustCompile(str string) *Regexp
Compile :返回 Regexp 对象,方便调用指针函数。
MustCompile :同Compile,解析表达式失败,会panic。
在匹配文本时,该正则表达式会尽可能早的开始匹配,并且在匹配过程中选择回溯搜索到的第一个匹配结果。这种模式被称为 leftmost-first ,另外一般情况下使用 MustCompile 即可。
使用regexp.Regexp对象来调用
Find 和 FindAll
- func (re *Regexp) Find(b []byte) []byte
- func (re *Regexp) FindAll(b []byte, n int) [][]byte
Find返回保管正则表达式re在b中的最左侧的一个匹配结果的[]byte切片。如果没有匹配到,会返回nil,最多匹配一个。
re := regexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.Find([]byte(`seafood fool`)))
re := regexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.FindAll([]byte(`seafood fool`), -1))
FindAll 功能与 Find 一样,只是返回全部满足条件的数据。
FindString 和 FindAllString
- func (re *Regexp) FindString(s string) string
- func (re *Regexp) FindAllString(s string, n int) []string
与 Find 和 FindAll 一样,只是针对字符串string操作。
FindIndex 和 FindAllIndex
- func (re *Regexp) FindIndex(b []byte) (loc []int)
- func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
FindIndex , 返回 b 中满足匹配字符串部分的起始位置,同样是**“leftmost-first”**原则,loc包含起止位置。如果没有找到,直接返回 nil 。
FindAllIndex ,功能和 FindIndex 保持一致,只是匹配多个, n 决定了匹配的位置。
FindStringIndex 和 FindAllStringIndex
- func (re *Regexp) FindStringIndex(s string) (loc []int)
- func (re *Regexp) FindAllStringIndex(s string, n int) [][]int
与 FindIndex 和 FindAllIndex 使用方式类似,只是针对的是字符串string。
FindStringSubmatch 和 FindAllStringSubmatch
- func (re *Regexp) FindStringSubmatch(s string) []string
FindStringSubmatch :采用左匹配原则,最多匹配一个,如果没有的话,返回 nil 。对于返回的 []string ,分别标示匹配的字符串,子串。
re := regexp.MustCompile(`a(x*)b(y|z)c`) fmt.Printf("%q\n", re.FindStringSubmatch("-axxxbyc-")) fmt.Printf("%q\n", re.FindStringSubmatch("-abzc-"))
输出结果:
["axxxbyc" "xxx" "y"]
["abzc" "" "z"]
- func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string
和 FindStringSubmatch 使用类似,只是能顾选择匹配的长度, -1 表示匹配到末尾。
re := regexp.MustCompile(`a(x*)b`) fmt.Printf("%q\n", re.FindAllStringSubmatch("-ab-", -1)) fmt.Printf("%q\n", re.FindAllStringSubmatch("-axxb-", -1)) fmt.Printf("%q\n", re.FindAllStringSubmatch("-ab-axb-", -1)) fmt.Printf("%q\n", re.FindAllStringSubmatch("-axxb-ab-", -1))
输出结果:
[["ab" ""]]
[["axxb" "xx"]]
[["ab" ""] ["axb" "x"]]
[["axxb" "xx"] ["ab" ""]]
FindSubmatchIndex 和 FindAllSubmatchIndex
- func (re *Regexp) FindSubmatchIndex(b []byte) []int
- func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int 计算子串在源串中的位置,已经存在 (x*) 等返回结果处理,如果没有返回 nil 。
另外, index 返回为 左闭右开 的模式,示例中的 2,2 表示空字符串的意思。 并且,不会存在重合匹配的,比如说"-axxb-ab-"去匹配 a(x*)b ,不会存在第一个 a 和最后一个 b 结合的情况,如果使用 Longest 就会匹配最长的。
re := regexp.MustCompile(`a(x*)b`) // Indices: // 01234567 012345678 // -ab-axb- -axxb-ab- fmt.Println(re.FindAllStringSubmatchIndex("-ab-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-axxb-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-ab-axb-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-axxb-ab-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-foo-", -1))
输出结果:
[[1 3 2 2]] // 2 2 表示为空
[[1 5 2 4]]
[[1 3 2 2] [4 7 5 6]]
[[1 5 2 4] [6 8 7 7]]
[]
FindStringSubmatchIndex 和 FindAllStringSubmatchIndex func (re *Regexp) FindStringSubmatchIndex(s string) []int func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int 和 FindSubmatchIndex , FindAllSubmatchIndex 保持一致。 Longest func (re *Regexp) Longest() 获取最长匹配的满足条件的内容。 re := regexp.MustCompile(`a(|b)`) fmt.Println(re.FindString("ab")) re.Longest() fmt.Println(re.FindString("ab"))
输出结果:
a
ab
下面这种情况不会最长匹配。
re := regexp.MustCompile(`a(x*)b`) re.Longest() fmt.Println(re.FindString("-axxb-ab-")) // axxb,不会存在第一个a和最后一个b组合的过程。
Match,MatchString和MatchReader
- func (re *Regexp) Match(b []byte) bool
- func (re *Regexp) MatchString(s string) bool
- func (re *Regexp) MatchReader(r io.RuneReader) bool
判断 b , s 和 r 返回的数据是否满足正则表达式,返回 true 或者 false 。
NumSubexp
- func (re *Regexp) NumSubexp() int
返回分组的数量。
re0 := regexp.MustCompile(`a.`) fmt.Printf("%d\n", re0.NumSubexp()) re := regexp.MustCompile(`(.*)((a)b)(.*)a`) fmt.Println(re.NumSubexp())
输出结果:
0
4
ReplaceAll 和 ReplaceAllString func (re *Regexp) ReplaceAll(src, repl []byte) []byte func (re *Regexp) ReplaceAllString(src, repl string) string ReplaceAllString 与 ReplaceAll 使用方式相同。 re := regexp.MustCompile(`a(x*)b`) fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("T"))) fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("$1"))) // $1表示匹配的第一个子串,这是ab的中间无字符串,所以$1为空,然后使用空去替换满足正则表达式的部分。 fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("$1W"))) // "$1W"等价与"$(1W)",值为空,将满足条件的部分完全替换为空。 fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("${1}W"))) // ${1}匹配(x*),保留。输出-W-xxW-
输出结果:
-T-T-
--xx-
---
-W-xxW-
s := "Hello World, 123 Go!" //定义一个正则表达式reg,匹配Hello或者Go reg := regexp.MustCompile(`(Hell|G)o`) s2 := "2019-12-01,test" //定义一个正则表达式reg2,匹配 YYYY-MM-DD 的日期格式 reg2 := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`) //最简单的情况,用“T替换”"-ab-axxb-"中符合正则"a(x*)b"的部分 reg3 := regexp.MustCompile("a(x*)b") fmt.Println(re.ReplaceAllString("-ab-axxb-", "T")) // -T-T- //${1}匹配"Hello World, 123 Go!"中符合正则`(Hell|G)`的部分并保留,去掉"Hello"与"Go"中的'o'并用"ddd"追加 rep1 := "${1}ddd" fmt.Printf("%q\n", reg.ReplaceAllString(s, rep1)) // Hellddd World, 123 Gddd! //首先,"2019-12-01,test"中符合正则表达式`(\d{4})-(\d{2})-(\d{2})`的部分是"2019-12-01",将该部分匹配'(\d{4})'的'2019'保留,去掉剩余部分 rep2 := "${1}" fmt.Printf("%q\n", reg2.ReplaceAllString(s2,rep2)) // 2019,test //首先,"2019-12-01,test"中符合正则表达式`(\d{4})-(\d{2})-(\d{2})`的部分是"2019-12-01",将该部分匹配'(\d{2})'的'12'保留,去掉剩余部分 rep3 := "${2}" fmt.Printf("%q\n", reg2.ReplaceAllString(s2,rep3)) // 12,test //首先,"2019-12-01,test"中符合正则表达式`(\d{4})-(\d{2})-(\d{2})`的部分是"2019-12-01",将该部分匹配'(\d{2})'的'01'保留,去掉剩余部分,并追加"13:30:12" rep4 := "${3}:13:30:12" fmt.Printf("%q\n", reg2.ReplaceAllString(s2,rep4)) // 01:13:30:12,test }
ReplaceAllFunc 和 ReplaceAllStringFunc
- func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
- func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string
将匹配出来满足条件的 []byte 作为参数传入函数中。
re := regexp.MustCompile(`[^aeiou]`) fmt.Println(re.ReplaceAllStringFunc("seafood fool", strings.ToUpper))
两者使用方式类似。
ReplaceAllLiteral 和 ReplaceAllLiteralString
- func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte
- func (re *Regexp) ReplaceAllLiteralString(src, repl string) string
匹配字面常量,不转换。
re := regexp.MustCompile(`a(x*)b`) fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "T")) fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "$1")) fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "${1}"))
输出结果:
-T-T-
-$1-$1-
-${1}-${1}-
关于 $1 说明:
Expand 和 ExpandString
- func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
- func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
Expand返回新生成的将template添加到dst后面的切片。在添加时,Expand会将template中的变量替换为从src匹配的结果。match应该是被FindSubmatchIndex返回的匹配结果起止位置索引。(通常就是匹配src,除非你要将匹配得到的位置用于另一个[]byte)
在template参数里,一个变量表示为格式如: $name 或 ${name} 的字符串,其中name是长度>0的字母、数字和下划线的序列。一个单纯的数字字符名如$1会作为捕获分组的数字索引;其他的名字对应(?P...)语法产生的命名捕获分组的名字。超出范围的数字索引、索引对应的分组未匹配到文本、正则表达式中未出现的分组名,都会被替换为空切片。
$name格式的变量名,name会尽可能取最长序列: $1x 等价于 ${1x} 而非 ${1}x , $10 等价于 ${10} 而非 ${1}0 。因此 $name 适用在后跟空格/换行等字符的情况, ${name} 适用所有情况。
如果要在输出中插入一个字面值 '$' ,在template里可以使用 $$ 。
其他示例
解析网址
flysnowRegexp := regexp.MustCompile(`^http://www.flysnow.org/([\d]{4})/([\d]{2})/([\d]{2})/([\w-]+).html$`) params := flysnowRegexp.FindStringSubmatch("http://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html") // 返回[]string{}数据类型 for _, param := range params { fmt.Println(param) }
输出结果:
http://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html
2018
01
20
golang-goquery-examples-selector
总结
终于介绍完啦!小伙伴们,这篇关于《Go语言正则表达式的使用详解》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!
-
236 收藏
-
426 收藏
-
179 收藏
-
248 收藏
-
195 收藏
-
165 收藏
-
473 收藏
-
377 收藏
-
384 收藏
-
246 收藏
-
110 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 标致的仙人掌
- 这篇文章内容太及时了,细节满满,太给力了,已加入收藏夹了,关注楼主了!希望楼主能多写Golang相关的文章。
- 2023-05-30 23:15:55
-
- yajie
- 细节满满,码起来,感谢师傅的这篇文章,我会继续支持!
- 2023-03-21 03:13:44
-
- 传统的皮带
- 这篇文章内容真及时,太详细了,真优秀,码住,关注大佬了!希望大佬能多写Golang相关的文章。
- 2023-03-04 11:20:45
-
- 不安的楼房
- 细节满满,收藏了,感谢老哥的这篇博文,我会继续支持!
- 2023-02-08 02:36:51
-
- 壮观的面包
- 这篇文章内容太及时了,很详细,赞 👍👍,收藏了,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-02-04 14:26:34
-
- 苹果月饼
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢大佬分享博文!
- 2023-01-28 09:18:57
-
- 多情的豆芽
- 这篇文章内容真是及时雨啊,博主加油!
- 2023-01-27 02:24:21
-
- 喜悦的果汁
- 这篇博文真及时,楼主加油!
- 2023-01-16 17:08:33
-
- 拼搏的蜡烛
- 这篇博文真及时,太全面了,太给力了,已加入收藏夹了,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-01-11 05:49:58
-
- 有魅力的网络
- 赞 👍👍,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢博主分享文章内容!
- 2023-01-05 13:47:49