Go 的 regexp 包提供了对正则表达式的支持。
所接受的正则表达式语法与 Perl、Python 及其他语言使用的通用语法相同。
搜索模式和输入文本都按 UTF-8 解释。
使用反引号(`)创建字符串时,反斜杠(\)没有任何特殊含义,也不会标记特殊字符的开头,比如制表符\t或换行符\n:
"\t\n" // regular string literal with 2 characters: a tab and a newline
`\t\n`// raw string literal with 4 characters: two backslashes, a 't', and an 'n'
因此,创建正则表达式时最好使用反引号,因为这样就不需要转义反斜杠:
"\\" // string with a single backslash
`\\` // string with 2 backslashes
RegExp类型要使用正则表达式,我们必须先编译字符串模式。
这里的编译指的是,把正则表达式的字符串模式转换成一种更易于处理的内部表示。
每个模式只需要编译一次,之后就可以多次使用编译后的正则表达式。
类型regexp.Regexp表示编译后的正则表达式。
我们可以使用函数regexp.Compile把字符串模式编译成regexp.Regexp。
如果编译失败,这个函数会返回nil和一个错误:
re, err := regexp.Compile(`(a|b)+`)
fmt.Println(re, err) // => (a|b)+ <nil>
re, err = regexp.Compile(`a|b)+`)
fmt.Println(re, err) // => <nil> error parsing regexp: unexpected ): `a|b)+`
函数MustCompile是Compile的一个方便的替代品:
re = regexp.MustCompile(`[a-z]+\d*`)
使用这个函数就不需要处理错误。
MustCompile should only be used when we know for sure the pattern does compile, as otherwise the program will panic.
Regexp有 16 个方法可以匹配正则表达式并识别匹配到的文本。
这些方法的名称都能被下面这个正则表达式匹配:
Find(All)?(String)?(Submatch)?(Index)?
All,该例程会依次匹配整个表达式的各个不重叠的匹配项。String,实参是字符串;否则是字节切片;返回值也会相应地调整。Submatch,返回值是一个切片,用来标识表达式中各个连续的子匹配。Index,匹配和子匹配用输入字符串中的字节下标对来标识。此外还有用于以下操作的方法:
总的来说,regexp包定义了 40 多个函数和方法。
下面我们会演示其中几个方法的用法。
这些函数以及其他函数的详细信息,请参阅 API 文档。
MatchString示例方法MatchString报告字符串中是否包含正则表达式的任何匹配项。
re = regexp.MustCompile(`[a-z]+\d*`)
b = re.MatchString("[a12]") // => true
b = re.MatchString("12abc34(ef)") // => true
b = re.MatchString(" abc!") // => true
b = re.MatchString("123 456") // => false
FindString示例方法FindString返回一个字符串,其中包含正则表达式最左边那个匹配项的文本。
re = regexp.MustCompile(`[a-z]+\d*`)
s = re.FindString("[a12]") // => "a12"
s = re.FindString("12abc34(ef)") // => "abc34"
s = re.FindString(" abc!") // => "abc"
s = re.FindString("123 456") // => ""
FindStringSubmatch示例方法FindStringSubmatch返回一个字符串切片,其中包含正则表达式最左边那个匹配项的文本,以及它的各个子表达式(如果有)的匹配文本。
可以用它来找出匹配捕获组的字符串。
返回值为nil表示没有匹配。
re = regexp.MustCompile(`[a-z]+(\d*)`)
sl = re.FindStringSubmatch("[a12]") // => []string{"a12","12"}
sl = re.FindStringSubmatch("12abc34(ef)") // => []string{"abc34","34"}
sl = re.FindStringSubmatch(" abc!") // => []string{"abc",""}
sl = re.FindStringSubmatch("123 456") // => <nil>
ReplaceAllString示例方法re.ReplaceAllString(src,repl)返回src的一个副本,并把正则表达式re的匹配项替换为替换字符串repl。
re = regexp.MustCompile(`[a-z]+\d*`)
s = re.ReplaceAllString("[a12]", "X") // => "[X]"
s = re.ReplaceAllString("12abc34(ef)", "X") // => "12X(X)"
s = re.ReplaceAllString(" abc!", "X") // => " X!"
s = re.ReplaceAllString("123 456", "X") // => "123 456"
Split示例方法re.Split(s,n)把文本s按该表达式切分成若干子串,并返回这些表达式匹配项之间的子串切片。
数量n决定最多返回多少个子串。
如果n<0,该方法返回所有子串。
re = regexp.MustCompile(`[a-z]+\d*`)
sl = re.Split("[a12]", -1) // => []string{"[","]"}
sl = re.Split("12abc34(ef)", 2) // => []string{"12","(ef)"}
sl = re.Split(" abc!", -1) // => []string{" ","!"}
sl = re.Split("123 456", -1) // => []string{"123 456"}
本包提供的 regexp 实现保证运行时间与输入大小成线性关系。
regexp包实现的是 RE2 正则表达式(\C 除外)。
其语法与 PCRE(“Perl 兼容正则表达式”)大体兼容,但也有一些差异。
详情请参阅这篇文章中的“注意事项”部分。