regexp包实现了正则表达式搜索。正则表达式采用RE2语法(除了\c、\C),和Perl、Python等语言的正则基本一致。

regexp

Find(All)?(String)?(Submatch)?(Index)?
  1. 如果’All’出现了,该方法会返回输入中所有互不重叠的匹配结果。如果一个匹配结果的前后(没有间隔字符)存在长度为0的成功匹配,该空匹配会被忽略。包含All的方法会要求一个额外的整数参数n,如果n>=0,方法会返回最多前n个匹配结果。

  2. 如果’String’出现了,匹配对象为字符串,否则应该是[]byte类型,返回值和匹配对象的类型是对应的。

  3. 如果’Submatch’出现了,返回值是表示正则表达式中成功的组匹配(子匹配/次级匹配)的切片。组匹配是正则表达式内部的括号包围的次级表达式(也被称为“捕获分组”),从左到右按左括号的顺序编号。,索引0的组匹配为完整表达式的匹配结果,1为第一个分组的匹配结果,依次类推。

  4. 如果’Index’出现了,匹配/分组匹配会用输入流的字节索引对表示result[2n:2n+1]表示第n个分组匹配的的匹配结果。如果没有’Index’,匹配结果表示为匹配到的文本。如果索引为负数,表示分组匹配没有匹配到输入流中的文本。

分组

1. (re)           编号的捕获分组
2. (?P<name>re)   命名并编号的捕获分组
3. (?:re)         不捕获的分组
4. (?flags)       设置当前所在分组的标志,不捕获也不匹配
5. (?flags:re)    设置re段的标志,不捕获的分组

func Match

func Match(pattern string, b []byte) (matched bool, err error)

Match检查b中是否存在匹配pattern的子序列。更复杂的用法请使用Compile函数和Regexp对象。

func MatchString

func MatchString(pattern string, s string) (matched bool, err error)

MatchString类似Match,但匹配对象是字符串。

func MatchReader

func MatchReader(pattern string, r io.RuneReader) (matched bool, err error)

MatchReader类似Match,但匹配对象是io.RuneReader。

type Regexp

Regexp代表一个编译好的正则表达式。Regexp可以被多线程安全地同时使用。

func Compile

func Compile(expr string) (*Regexp, error)

Compile解析并返回一个正则对象。

  1. 在匹配文本时,该正则表达式会尽可能早的开始匹配,并且在匹配过程中选择回溯搜索到的第一个匹配结果,这种模式被称为“leftmost-first”。

  2. Perl、Python和其他实现都采用了这种模式,但本包的实现没有回溯的损耗。对POSIX的“leftmost-longest”模式,参见CompilePOSIX。

func CompilePOSIX

func CompilePOSIX(expr string) (*Regexp, error)
  1. 类似Compile但会将语法约束到POSIX ERE(egrep)语法,并将匹配模式设置为leftmost-longest(最左最长方式搜索)不支持\w,\W等perl写法

  2. 在匹配文本时,该正则表达式会尽可能早的开始匹配,并且在匹配过程中选择搜索到的最长的匹配结果,这种模式被称为“leftmost-longest”

func MustCompile

func MustCompile(str string) *Regexp

MustCompile类似Compile但会在解析失败时panic,主要用于全局正则表达式变量的安全初始化。

func MustCompilePOSIX

func MustCompilePOSIX(str string) *Regexp

MustCompilePOSIX类似CompilePOSIX但会在解析失败时panic,主要用于全局正则表达式变量的安全初始化。

regexp.Compile 和 regexp.CompilePOSIX 有什么区别

  1. Perl和POSIX兼容的正则表达式在很大程度上相似,但在一些关键方面有所不同,例如子匹配。
  2. 假设你有一个正则表达式(foo | foobar)。当将这个表达式与匹配多个子表达式的字符串进行匹配时(例如,foobarbaz将同时匹配子模式foo和foobar),与Perl兼容的正则表达式将返回第一个匹配(foo),而与POSIX兼容的正则表达式将返回最长的匹配(foobar)。
func main() {
    pattern := "(foo|foobar)"
    str := []byte("foobarbaz")

    rPCRE, _ := regexp.Compile(pattern)
    rPOSIX, _ := regexp.CompilePOSIX(pattern)

    matchesPCRE := rPCRE.Find(str)
    fmt.Println(string(matchesPCRE))
    // prints "foo"

    matchesPOSIX := rPOSIX.Find(str)
    fmt.Println(string(matchesPOSIX))
    // prints "foobar"
}

func (*Regexp) String

func (re *Regexp) String() string

String返回用于编译成正则表达式的字符串。

func (*Regexp) Match

func (re *Regexp) Match(b []byte) bool

Match检查b中是否存在匹配pattern的子序列。

func (*Regexp) MatchString

func (re *Regexp) MatchString(s string) bool

MatchString类似Match,但匹配对象是字符串。

func (*Regexp) Find

func (re *Regexp) Find(b []byte) []byte

Find返回保管正则表达式re在b中的最左侧的一个匹配结果的[]byte切片。如果没有匹配到,会返回nil。

func (*Regexp) FindString

func (re *Regexp) FindString(s string) string

Find返回保管正则表达式re在b中的最左侧的一个匹配结果的字符串。如果没有匹配到,会返回"“;但如果正则表达式成功匹配了一个空字符串,也会返回”"。如果需要区分这种情况,请使用FindStringIndex 或FindStringSubmatch。

https://studygolang.com/pkgdoc

举例

匹配判断

匹配判断使用Match方法或MatchString方法,两者区别仅是Match参数为字节类型,MatchString为字符串类型

//匹配,参数为字符串
matchResult,_ := regexp.MatchString("study", text)
fmt.Println(matchResult) //true

//匹配,参数为[]byte
byteMatchResult,_ := regexp.Match(`\d+`, []byte(text))
fmt.Println(byteMatchResult) //true

查找

查找主要方法有FindString、FindAllString、FindStringIndex

//查询所有,指定参数最多查询个数为2, 负数表示查所有,如-1
queryAllResult := regexp.MustCompilePOSIX(`study`).FindAllString(text, 2)
fmt.Println(queryAllResult) //[study study]

//查询第一个匹配字符串
queryResult := regexp.MustCompile("study").FindString(text)
fmt.Println(queryResult) //study

//最短匹配
shortTxt := regexp.MustCompile(`st|study`).FindString(text)
fmt.Println(shortTxt) //st

//最长匹配
longTxt := regexp.MustCompilePOSIX(`st|study`).FindString(text)
fmt.Println(longTxt) //study

//查询匹配串位置
findIdxResult := regexp.MustCompile(`study`).FindStringIndex(text)
println(findIdxResult)

//Unicode使用,如\p{Han}表示中文
hanResult := regexp.MustCompile(`[\p{Han}]+`).FindString(text)
println(hanResult) //好好学习

//非贪婪,添加标识?
notGreedyResult := regexp.MustCompile(`\d+?3`).FindString(text)
println(notGreedyResult) //23
//贪婪
greedyResult := regexp.MustCompile(`\d+3`).FindString(text)
println(greedyResult) //2333

//分组
groupResult := regexp.MustCompile(`(\d+)\s+(\d+)`).FindString(text)
println(groupResult) //11 2333
//分组打标签
tagGroupResult := regexp.MustCompile(`(?P<tagName_1>\d+)\s+(?P<tagName_2>\d+)`).FindString(text)
println(tagGroupResult) //11 2333

//非贪婪模式标识:(?U),切换为贪婪模式用方法Longest
notGreedyReg := regexp.MustCompile(`(?U)\d+3`)
notGreedyResult := notGreedyReg.FindString(text)
println(notGreedyResult) //23
//通过方法Longest转为贪婪模式
notGreedyReg.Longest()
changeGreedyResult := notGreedyReg.FindString(text)
println(changeGreedyResult) //2333
//贪婪模式,不带标识(?U)
greedyResult := regexp.MustCompile(`\d+3`).FindString(text)
println(greedyResult)//2333

替换

替换主要方法有ReplaceAllString、ReplaceAllStringFunc,其中ReplaceAllStringFunc表示使用自定义方法定义替换规则。

//自定义替换规则函数
func updateDisplose(text string) string{
	if strings.Contains(text, "5"){
		return text+"++"
	}
	return text
}

//替换
updateResult := regexp.MustCompile("<.*?>").ReplaceAllString(text, "")
fmt.Println(updateResult) //apple study hard ,好好学习, 11 2333 33 study, good,天天向上 study 1243 53,

//替换,使用函数指定替换规则
updateFuncResult := regexp.MustCompile(`\d+`).ReplaceAllStringFunc(text, updateDisplose)
println(updateFuncResult) //<p>apple study hard ,好好学习, 11 2333 33 study, good,天天向上 study 1243 53++, </p>

//分组查找替换
expandReg := regexp.MustCompile(`(\w+).*(\d+)`)
template := "hello $1, study $2"
//dst := "info:"
//subMatchIdx := expandReg.FindStringSubmatchIndex(text)
//expandResult :=expandReg.ExpandString([]byte(dst), template, text, subMatchIdx)
expandResult :=expandReg.ExpandString(nil, template, text, expandReg.FindStringSubmatchIndex(text))
fmt.Printf("%s\n", expandResult) //hello p, study 3