Go语言正则表达式的使用详解
正则表达式是一种进行模式匹配和文本操纵的功能强大的工具。正则表达式灵活、易用,按照它的语法规则,随需构造出的匹配模式就能够从原始文本中筛选出几乎任何你想要得到的字符组合。
准则
- 默认是最短匹配,只要字符串满足条件就返回。
- 如果没有匹配到,都是返回为nil。
- 如果需要做最长匹配,调用Longest()函数。
- 正则表达式功能:匹配(macth),查找(find)和替换(replace)。
- 存在长度选择的函数,传入<0的数字表示匹配全部。
使用regexp调用
Match,MatchReader和MatchString
//判断b中是够包含pattern能够组成的任意字符串 funcMatch(patternstring,b[]byte)(matchedbool,errerror) //判断readerr中返回的字符串是否包含pattern能够组成的任意字符串 funcMatchReader(patternstring,rio.RuneReader)(matchedbool,errerror) //判断字符串s中是否包含pattern能够组成的任意字符串 funcMatchString(patternstring,sstring)(matchedbool,errerror)
Compile和MushCompile
funcCompile(exprstring)(*Regexp,error)
funcMustCompile(strstring)*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,nint)[][]byte
Find返回保管正则表达式re在b中的最左侧的一个匹配结果的[]byte切片。如果没有匹配到,会返回nil,最多匹配一个。
re:=regexp.MustCompile(`foo.?`) fmt.Printf("%q\n",re.Find([]byte(`seafoodfool`)))
re:=regexp.MustCompile(`foo.?`) fmt.Printf("%q\n",re.FindAll([]byte(`seafoodfool`),-1))
FindAll功能与 Find一样,只是返回全部满足条件的数据。
FindString和FindAllString
- func(re*Regexp)FindString(sstring)string
- func(re*Regexp)FindAllString(sstring,nint)[]string
与 Find和 FindAll一样,只是针对字符串string操作。
FindIndex和FindAllIndex
- func(re*Regexp)FindIndex(b[]byte)(loc[]int)
- func(re*Regexp)FindAllIndex(b[]byte,nint)[][]int
FindIndex,返回 b中满足匹配字符串部分的起始位置,同样是**“leftmost-first”**原则,loc包含起止位置。如果没有找到,直接返回 nil。
FindAllIndex,功能和 FindIndex保持一致,只是匹配多个, n决定了匹配的位置。
FindStringIndex和FindAllStringIndex
- func(re*Regexp)FindStringIndex(sstring)(loc[]int)
- func(re*Regexp)FindAllStringIndex(sstring,nint)[][]int
与 FindIndex和 FindAllIndex使用方式类似,只是针对的是字符串string。
FindStringSubmatch和FindAllStringSubmatch
- func(re*Regexp)FindStringSubmatch(sstring)[]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(sstring,nint)[][]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,nint)[][]int计算子串在源串中的位置,已经存在 (x*)等返回结果处理,如果没有返回 nil。
另外, index返回为 左闭右开的模式,示例中的 2,2表示空字符串的意思。并且,不会存在重合匹配的,比如说"-axxb-ab-"去匹配 a(x*)b,不会存在第一个 a和最后一个 b结合的情况,如果使用 Longest就会匹配最长的。
re:=regexp.MustCompile(`a(x*)b`) //Indices: //01234567012345678 //-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))
输出结果:
[[1322]]//22表示为空
[[1524]]
[[1322][4756]]
[[1524][6877]]
[]
FindStringSubmatchIndex和FindAllStringSubmatchIndex func(re*Regexp)FindStringSubmatchIndex(sstring)[]int func(re*Regexp)FindAllStringSubmatchIndex(sstring,nint)[][]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(sstring)bool
- func(re*Regexp)MatchReader(rio.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,replstring)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:="HelloWorld,123Go!" //定义一个正则表达式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}匹配"HelloWorld,123Go!"中符合正则`(Hell|G)`的部分并保留,去掉"Hello"与"Go"中的'o'并用"ddd"追加 rep1:="${1}ddd" fmt.Printf("%q\n",reg.ReplaceAllString(s,rep1))//HelldddWorld,123Gddd! //首先,"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,replfunc([]byte)[]byte)[]byte
- func(re*Regexp)ReplaceAllStringFunc(srcstring,replfunc(string)string)string
将匹配出来满足条件的 []byte作为参数传入函数中。
re:=regexp.MustCompile(`[^aeiou]`) fmt.Println(re.ReplaceAllStringFunc("seafoodfool",strings.ToUpper))
两者使用方式类似。
ReplaceAllLiteral和ReplaceAllLiteralString
- func(re*Regexp)ReplaceAllLiteral(src,repl[]byte)[]byte
- func(re*Regexp)ReplaceAllLiteralString(src,replstring)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,templatestring,srcstring,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:=rangeparams{ fmt.Println(param) }
输出结果:
http://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html
2018
01
20
golang-goquery-examples-selector
总结
到此这篇关于Go语言正则表达式的使用详解的文章就介绍到这了,更多相关Go正则表达式使用内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。