目录
使用Go正则表达式
Go语言中使用regexp包来处理正则表达式。下面介绍regexp包的使用方法和技巧。
1、regexp包的常用函数
1.1、获取正则对象。
regexp包提供了Compile()函数和MustCompile()函数来编译一个正则表达式,如果成功则返回Regexp对象。Compile()函数的定义如下:
func Compile(expr string)(*Regexp,error)
MustCompile()函数与Compile()函数类似,它们的差异是:失败时MustCompile()函数会宕机,而Compile()函数则不会。MustCompile()函数的定义如下:
func MustCompile(str string)*Regexp
Compile()函数和MustCompile()函数的使用示例如下:
reg1, err := regexp.Compile(`\d+`)
reg2 := regexp.MustCompile(`\d+`)
1.2、匹配检测
regexp包提供了MatchString()方法和Match()方法,来测试字符串是否匹配正则表达式。它们的定义如下:
func(re *Regexp)MatchString(s string)bool
func (re *Regexp)Match(b []byte)bool
MatchString()方法和Match()方法的使用示例如下:
import (
"fmt"
"regexp"
)
func main() {
text := "Hello Gopher, Hello Go Web"
reg := regexp.MustCompile(`\w+`)
fmt.Println(reg.MatchString(text))//true
//是否匹配字符串
//.匹配任意一个字符,*匹配零个或多个,优先匹配更多(贪婪)
match, _ := regexp.MatchString("H(.*)d!", "Hello World!")
fmt.Println(match)//true
//通过Compile来使用一个优化过的正则对象
r, _ := regexp.Compile("H(.*)d!")
fmt.Println(r.MatchString("Hello World!"))//true
}
1.3、查找
regexp包提供了FindString()、FindAllString()、FindAll()等方法来查找字符和字符串。
- FindString()方法用于查找匹配指定模式的字符串,返回左侧第一个匹配的结果。其定义如下:
func (re *Regexp)Findstring(s string) string
text := "hello world"
reg, _ := regexp.Compile(`h.{4}`)
res := reg.FindString(text)
fmt.Println(res)//hello
- FindAllString()方法用于查找匹配指定模式的字符串数组,会返回多个匹配的结果。其中n用于限定查找数量,一1表示不限制。其定义如下:
func (re *Regexp)FindAllString(s string,n int)[]string
FindAllString()方法的使用示例如下:
text := "Hello Gopher, Hello Go Web"
reg := regexp.MustCompile(`\w+`)
var arr []string
arr = reg.FindAllString(text, -1)
fmt.Println(arr)
for _, v := range arr {
fmt.Println(v)
}
- FindAll(方法用于在[]byte中进行查找,返回[][]byte。其定义如下:
func (re *Regexp)FindAll(b []byte,n int) [][]byte
text := []byte("hello world")
reg := regexp.MustCompile(`h.{4}`)
res := reg.FindAll(text, -1)
for _, v := range res {
fmt.Println(string(v))
}
- FindStringSubmatch()方法用于查找满足匹配的最左边的最短匹配字符串,如果匹配成功,则返回正则表达式的子匹配项。
其定义如下:
func (re *Regexp)FindstringSubmatch(s string).[]string
FindStringSubmatch()方法的使用示例如下:
re := regexp.MustCompile(`who(o*)a(a|m)i`)
fmt.Printf("%q\n", re.FindStringSubmatch("-whooooaai-")) //["whooooaai" "ooo" "a"]
fmt.Printf("%q\n", re.FindStringSubmatch("-whoami-"))//["whoami" "" "m"]
- FindAllStringSubmatch()方法用于查找满足匹配的最左边的最短匹配字符串,如果匹配成功,则返回正则表达式的子匹配项。其中参数门用于选择匹配的长度,-1表示匹配到末尾。
其定义如下:
func (re *Regexp)FindAllStringSubmatch(s string,n int)[][]string
FindAllStringSubmatch()方法的使用示例如下:
re := regexp.MustCompile(`w(a*)i`)
fmt.Printf("%q\n", re.FindAllStringSubmatch("-wi-", -1)) //[["wi" ""]]
fmt.Printf("%q\n", re.FindAllStringSubmatch("-waaai-", -1)) //[["waaai" "aaa"]]
fmt.Printf("%q\n", re.FindAllStringSubmatch("-wi-wai-", -1)) //[["wi" ""] ["wai" "a"]]
fmt.Printf("%q\n", re.FindAllStringSubmatch("-waai-wi-", -1)) //[["waai" "aa"] ["wi" ""]]
1.4、查找匹配位置
regexp包提供了FindStringlndex()、FindIndex()、FindAllStringlndex()方法来获取匹配正则子字符串的位置。
- Findlndex()方法用于查找匹配的开始位置和结束位置。如果匹配成功,则返回包含最左侧匹配结果的起止位置的切片。其定义如下:
func.(re *Regexp) FindIndex(b []byte)(loc []int)
text := "hello world"
reg := regexp.MustCompile(`l`)
fmt.Println(reg.FindIndex([]byte(text)))//[2 3]
- FindAlllndex()方法用于查找所有匹配的开始位置和结束位置。
如果匹配成功,则返回包含最左侧匹配结果的起止位置的切片。其定义如下:
func.(re *Regexp) FindstringIndex(s string)(loc []int)
text := "hello world"
reg := regexp.MustCompile(`l`)
fmt.Println(reg.FindAllIndex([]byte(text), -1))//[[2 3] [3 4] [9 10]]
- FindStringlndex()方法用于查找第1次匹配指定子字符串的索引的起始索引和结束索引。如果匹配成功,则返回包含最左侧匹配结果的起止位置的切片。
其定义如下:
func (re *Regexp)FindstringIndex(s string)(loc []int)
text := "hello world"
reg := regexp.MustCompile(`l`)
fmt.Println(reg.FindStringIndex(text))//[2 3]
- FindAllStringIndex()方法用于返回包含最左侧匹配结果的起止位置的切片。其定义如下:
func (re *Regexp)FindAllStringIndex(s string,n int)[][]int
reg := regexp.MustCompile(`llo`)
fmt.Println(reg.FindAllStringIndex("Hello World!", -1))//[[2 5]]
1.5、替换
regexp包提供了ReplaceAllString()、ReplaceAll()方法来替换字符,它们的定义如下:
func (re *Regexp)ReplaceAllString(src,repl string) string
func (re *Regexp)ReplaceAll(src,repl []byte) []byte
替换时可以使用反向引用$1、$2来引用匹配的子模式内容,示例如下。
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`Go(\w+)`)
fmt.Println(re.ReplaceAllString("Hello Gopher, Hello GoLang", "Java$1")) //Hello Javapher, Hello JavaLang
re = regexp.MustCompile(`w(a*)i`)
fmt.Printf("%s\n", re.ReplaceAll([]byte("-wi-waaaaai-"), []byte("T"))) //-T-T-
//$1标识匹配的第一个子串,这是wi的中间无字符串,所以$1为空
//然后使用空去替换满足正则表达式的部分
fmt.Printf("%s\n", re.ReplaceAll([]byte("-wi-waaaaai-"), []byte("$1"))) //--aaaaa-
//"$1W"等价与"$(1W)",如果值为空,则将满足条件的部分完全替换为空
fmt.Printf("%s\n", re.ReplaceAll([]byte("-wi-waaaaai-"), []byte("$1W"))) //---
//${1}匹配(x*)
fmt.Printf("%s\n", re.ReplaceAll([]byte("-wi-waaaaai-"), []byte("${1}W")))//-W-aaaaaW-
}
1.6、分割
strings包提供了Split()、SplitN()、SplitAfter()、SplitAfterN()这4个函数来处理正则分割字符串。
- Split()函数的定义如下:
func Split(s,sep string) []string
其中,s为被正则分割的字符串,sep为分隔符。Split()函数的使用示例如下:
s := "I_Love_Go_Web"
res := strings.Split(s, "_")
for _, v := range res {
fmt.Println(v)
}
- SplitN()函数的定义如下:
func SplitN(s,sep string,n int)[]string
其中,S为正则分割字符串,Sep为分隔符,n为控制分割的片数,-1为不限制。如果匹配,则函数会返回一个字符串切片。SplitN()函数的使用示例如下:
value := "a|b|c|d"
//分割成3部分
result := strings.SplitN(value, "|", 3)
for _, v := range result {
fmt.Println(v)
}
- SplitAfter()函数的定义如下:
func SplitAfter(s,sep string)
- SplitAfterN()函数的定义如下:
func SplitAfterN(s,sep string,n int)[]string
以上4个函数都是通过sep参数对传入对字符串参数s进行分割的,返回类型为[]string。如果sep为空,则相当于分成一个UTF-8字符。
在以上4个函数中,Split(s,sep)和SplitN(s,sep,-1)等价;SplitAfter(s,sep)和SplitAfterN(s,sep,-1)等价。
s := "I_Love_Go_Web"
res1 := strings.SplitAfter(s, "_")
for _, v := range res1 {
fmt.Println(v)
}
res2 := strings.SplitAfterN(s, "_", 2)
for _, v := range res2 {
fmt.Println(v)
}
I_
Love_
Go_
Web
I_
Love_Go_Web
2、regexp包常见应用示例
2.1、匹配电话号码
import (
"fmt"
"regexp"
)
func main() {
fmt.Println(findPhoneNumber("13812348888")) //true
fmt.Println(findPhoneNumber("0203234")) //false
fmt.Println(findPhoneNumber("123456789")) //false
}
func findPhoneNumber(str string) bool {
//创建一个正则表达式匹配规则对象
reg := regexp.MustCompile("^1[3456789]\\d{9}$")
res := reg.FindAllString(str, -1)
if res == nil {
return false
}
return true
}
2.2、匹配Email
import (
"fmt"
"regexp"
)
func main() {
fmt.Println(findEmail("8888@aa.com"))//true
fmt.Println(findEmail("shir?don@qq.com"))//false
fmt.Println(findEmail("234@yeah.net"))//true
}
func findEmail(str string) bool {
reg := regexp.MustCompile("^[a-zA-Z0-9_]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+")
res := reg.FindAllString(str, -1)
if res == nil {
return false
}
return true
}