Golang 正则表达式使用小结

golang Regexp主要提供如下正则所表示的16个方法:

Find(All)?(String)?(Submatch)?(Index)?

若带All,该方法返回一个所有递进匹配结果的slice;该方法需要额外传一个整数n,若n>=0,至多返回n个匹配或子匹配,若x<0,返回全部。

若带String,该方法传入的参数需是string,否则为字节slice,返回结果也为对应的string。

若带Submatch,该方法返回表达式递进的子匹配slice(子匹配匹配以括号扩起的表达式,也称作匹配组),该slice以左括号从左到右的顺序返回匹配结果,即第0个为匹配整个表达式的结果,第1个为匹配第一个左括号所表示表达式的结果,以此类推。

若带Index,匹配与子匹配使用字节位置索引对来标识,result[2n:2n+1]标识第n个子匹配的索引。

也有一些方法不属上述正则所表示的范围。

1 基础用法

接下来看一个简单的例子。如下代码,在使用前首先将正则表达式编译,然后对多组字符串判断是否匹配。

package main

import (
	"fmt"
	"regexp"
)

var (
	p = regexp.MustCompile(`^[a-z]+\[\d+\]$`)
)

func main() {
	fmt.Println(p.MatchString("larry[12]"))
	fmt.Println(p.MatchString("jacky[12]"))
	fmt.Println(p.MatchString("linda[a12]"))
}

若仅一次性简单判断字符串是否匹配,也可以不创建Regexp,直接调用regexp包函数。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	fmt.Println(regexp.Match(`\w+`, []byte("hello")))
	fmt.Println(regexp.MatchString(`\d+`, "hello"))
}

常用方法示例:

package main

import (
	"fmt"
	"regexp"
)

func main() {
	p := regexp.MustCompile(`a.`)
	fmt.Println(p.Find([]byte("ababab")))
	fmt.Println(p.FindString("ababab"))
	fmt.Println(p.FindAllString("ababab", -1))
	fmt.Println(p.FindAllStringIndex("ababab", -1))

	q, _ := regexp.Compile(`^a(.*)b$`)
	fmt.Println(q.FindAllSubmatch([]byte("ababab"), -1))
	fmt.Println(q.FindAllStringSubmatch("ababab", -1))
	fmt.Println(q.FindAllStringSubmatchIndex("ababab", -1))

	r := regexp.MustCompile(`(?m)(key\d+):\s+(value\d+)`)
	content := []byte(`
        # comment line
        key1: value1
        key2: value2
        key3: value3
    `)
	fmt.Println(string(r.Find(content)))
	for _, matched := range r.FindAll(content, -1) {
		fmt.Println(string(matched))
	}
	for _, mutiMatched := range r.FindAllSubmatch(content, -1) {
		for _, matched := range mutiMatched {
			fmt.Println(string(matched))
		}
	}
}

2 进阶用法

2.1 Split

Split方法返回对传入字符串以表达式为分割符的子串slice,第二个参数n指定最多返回的子串数,负数表示返回所有子串。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	for _, sub := range regexp.MustCompile(`a+`).Split("heaallo woarld", -1) {
		fmt.Println(sub)
	}
}

2.2 Replace

如下代码,ReplaceAllString返回源字符串将匹配部分替换为字符串模板的拷贝,替换模板采用$符标识第几个替换组,如$1标识1第一个子匹配组。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	p := regexp.MustCompile(`(?P\w+)\s+(?P\w+)`)
	names := p.SubexpNames()
	fmt.Println(p.ReplaceAllString("hello world",
		fmt.Sprintf("$%s $%s", names[2], names[1])))
}

2.3 Expand

Expand将匹配模板所匹配部分叠加至dst尾部并返回。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	content := []byte(`
	# json fragment
	"id": "dbsuye23sd83d8dasf7",
	"name": "Larry",
	"birth_year": 2000
	`)
	p := regexp.MustCompile(`(?m)"(?P\w+)":\s+"?(?P[a-zA-Z0-9]+)"?`)
	var dst []byte
	tpl := []byte("$key=$value\n")
	for _, submatches := range p.FindAllSubmatchIndex(content, -1) {
		dst = p.Expand(dst, tpl, content, submatches)
	}
	fmt.Println(string(dst))
}

参考资料

[1] https://godoc.org/regexp

[2] https://godoc.org/regexp/syntax

评论

正在加载评论......