go 正则表达式

文章目录

        • 将 正则表达式字符串 转义为普通字符串:
        • 检测字符串中是否含有匹配在 pattern 的子序列
      • 正则表达式对象 Regexp
        • 函数 Complie
        • 函数 CompliePOSIX
        • 函数 MustCompile
        • 函数 MustCompliePOSIX
        • 方法 String
        • 方法 LiteralPrefix
        • 方法 NumSubexp
        • 方法 SubexpNames
        • 方法 Longest
        • 方法 Match
        • 方法 MatchString
        • 方法 MatchReader
        • 方法 Find
        • 方法FindString
        • 方法 Findindex
        • 方法 FindStringIndex
        • 方法 FindReaderIndex
        • 方法 FindSubmatch
        • 方法 FindStringSubmatch
        • 方法 FindSubmathcIndex
        • 方法FindStringSubmatchIndex
        • 方法 FindReaderSubmatchIndex
        • 方法 FindAll
        • 方法 FindAllString
        • 方法 FindAllIndex
        • 方法 FindAllStringIndex
        • 方法 FindAllSubmatch
        • 方法 FindAllStringSubmatch
        • 方法 FindAllSubmatchIndex
        • 方法 FindAllStringSubmatchIndex
        • 方法 Split
        • 方法 Expand
        • 方法 ExpandString
        • 方法 ReplaceAllLiteral
        • 方法 ReplaceAllLiteral
        • 方法 ReplaceAll
        • 方法 ReplaceAllString
        • 方法 ReplaceAllFunc
        • 方法 ReplaceAllStringFunc

正则表达式基本和 python 的一致

regexp 标准库文档:https://studygolang.com/pkgdoc

将 正则表达式字符串 转义为普通字符串:

func QuoteMeta(s string) string

例如,QuoteMeta('a.b')会返回'a\.b'

检测字符串中是否含有匹配在 pattern 的子序列

func Match(pattern string, b []byte) (matched bool, err error)
func MatchString(pattern string, s string) (matched bool, err error)
func MatchReader(pattern string, r io.RuneReader) (matched bool, err error)

这a个函数类似,一个匹配对象是二进制切片,一个匹配对象是字符串,一个匹配对象是 io.RuneReader,使用举例:

matched, err := regexp.MatchString("foo.*", "seafood")
fmt.Println(matched, err)
matched, err = regexp.MatchString("bar.*", "seafood")
fmt.Println(matched, err)
matched, err = regexp.MatchString("a(b", "seafood")
fmt.Println(matched, err)
fmt.Println("--------------------------------------")

 matched, err = regexp.Match("foo.*", []byte("seafood"))
 fmt.Println(matched, err)
 matched, err = regexp.Match("bar.*", []byte("seafood"))
 fmt.Println(matched, err)
 matched, err = regexp.Match("a(b", []byte("seafood"))
 fmt.Println(matched, err)

 fmt.Println("--------------------------------------")
 f, err := os.Open("/home/hongyu/go/src/test/regexp/matchreader.txt")
 if err != nil {
  fmt.Println("open file err", err)
 }
 rr := bufio.NewReader(f)
 defer f.Close()

 matched, err = regexp.MatchReader("foo.*", rr)
 fmt.Println(matched, err)
 matched, err = regexp.MatchReader("bar.*", rr)
 fmt.Println(matched, err)
 matched, err = regexp.MatchReader("a(b", rr)
 fmt.Println(matched, err)
/* 输出
true 
false 
false error parsing regexp: missing closing ): `a(b`
*/

正则表达式对象 Regexp

type Regexp struct {
    // 内含隐藏或非导出字段
}

Regexp 表示一个编译好的正则表达式

函数 Complie

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

Compile 用来解析正则表达式 expr 是否合法,如果合法,则返回一个 Regexp 对象

函数 CompliePOSIX

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

CompilePOSIX 的作用和 Compile 一样, 不同的是,CompilePOSIX 使用 POSIX 语法,同时,它采用最左最长方式搜索,而 Compile 采用最左最短方式搜索.

函数 MustCompile

func MustCompile(str string) *Regexp

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

函数 MustCompliePOSIX

func MustCompilePOSIX(str string) *Regexp

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

方法 String

func (re *Regexp) String() string

返回 正则表达式字符串

方法 LiteralPrefix

func (re *Regexp) LiteralPrefix() (prefix string, complete bool)

返回所有匹配项都共同拥有的前缀(去除可变元素)

  • prefix:共同拥有的前缀
  • complete:如果 prefix 就是正则表达式本身,则返回 true,否则返回 false
func main() {
    reg := regexp.MustCompile(`Hello[\w\s]+`)
    fmt.Println(reg.LiteralPrefix())      // Hello false
    reg = regexp.MustCompile(`Hello`)
    fmt.Println(reg.LiteralPrefix())      // Hello true
}

方法 NumSubexp

func (re *Regexp) NumSubexp() int

NumSubexp 返回该正则表达式中捕获分组的数量。

func main() {
reg := regexp.MustCompile(`(?U)(?:Hello)(\s+)(\w+)`)
fmt.Println(reg.NumSubexp())               // 2
}

方法 SubexpNames

func (re *Regexp) SubexpNames() []string

返回 re 中的分组名称列表,未命名的分组返回空字符串

func main() {
re := regexp.MustCompile("(?PHello)(World)")
 fmt.Printf("%q\n", re.SubexpNames())      // ["" "Hello" ""]
}

方法 Longest

func (re *Regexp) Longest()

Longest 让正则表达式在之后的搜索中都采用 “贪婪” 模式,切换为 贪婪模式。(默认就是贪婪模式)

func main() {
    text := `Hello World, 123 Go!`
    pattern := `(?U)H[\w\s]+o` // 正则标记“非贪婪模式”(?U)
    reg := regexp.MustCompile(pattern)
    fmt.Printf("%q\n", reg.FindString(text))      // Hello
    reg.Longest()                                             // 切换到“贪婪模式”
    fmt.Printf("%q\n", reg.FindString(text))      // Hello Wo    
}

方法 Match

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

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

text = `Hello World, 123 Go!`
pattern = `H[\w\s]`
reg = regexp.MustCompile(pattern)
fmt.Println(reg.Match([]byte(text)))            // true

方法 MatchString

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

Match()

方法 MatchReader

func (re *Regexp) MatchReader(r io.RuneReader) bool

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

方法 Find

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

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

reg = regexp.MustCompile(`\w+ `)
fmt.Printf("%q\n", reg.Find([]byte("Hello World!")))      // "Hello "

方法FindString

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

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

re := regexp.MustCompile("fo.?")
fmt.Printf("%q\n", re.FindString("seafood"))       // "foo"
fmt.Printf("%q\n", re.FindString("meat"))            // ""

方法 Findindex

func (re *Regexp) FindIndex(b []byte) (loc []int)

返回 b byte切片左侧第一处与正则表达式 re 相匹配的子切片所在的起止索引位置,如果没有匹配到,返回 [] 空切片:

re = regexp.MustCompile("fo.?")
 fmt.Println(re.FindIndex([]byte("seafoodfood")))    // [3, 6]
 fmt.Println(re.FindIndex([]byte("meat")))       // []

方法 FindStringIndex

func (re *Regexp) FindStringIndex(s string) (loc []int)

FindIndex,不同的是匹配对象是 字符串类型。

方法 FindReaderIndex

func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int)

FindIndex,不同的是匹配对象是 io.RunReader 接口类型。

re = regexp.MustCompile("fo.?")
f, err = os.Open("/home/hongyu/go/src/test/regexp/matchreader.txt")
if err != nil {
    fmt.Println("open file err", err)
}
fmt.Println(re.FindReaderIndex(bufio.NewReader(f)))
f.Close()

方法 FindSubmatch

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

在 b 中查找 re 中编译好的正则表达式,并返回第一个匹配的内容, 同时返回(可能有的)分组匹配的结果的 [][]byte 切片(子组)。

 re = regexp.MustCompile(`(\w)(\w)+`)
 fmt.Printf("%q\n", re.FindSubmatch([]byte("Hello World!")))     // ["Hello" "H" "o"]

方法 FindStringSubmatch

func (re *Regexp) FindStringSubmatch(s string) []string

FindSubmatch

方法 FindSubmathcIndex

func (re *Regexp) FindSubmatchIndex(b []byte) []int

功能类似于 FindSubmatch, 不同的地方是返回的是匹配的子切片的索引:

 re = regexp.MustCompile(`(\w)(\w)+`)
 fmt.Println(re.FindSubmatchIndex([]byte("Hello World!")))   # [0 5 0 1 4 5], 0~5-1 == Hello, 0~1-1 == H, 4~5-1 == o

方法FindStringSubmatchIndex

func (re *Regexp) FindStringSubmatchIndex(s string) []int

FindSubmatchIndex

方法 FindReaderSubmatchIndex

func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int

FindSubmatchIndex

方法 FindAll

func (re *Regexp) FindAll(b []byte, n int) [][]byte

返回 b 中所有与 正则表达式 re 相匹配的内容, 返回 [][]byte, 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项.

 reg = regexp.MustCompile("a.c")
 fmt.Printf("%q\n", reg.FindAll([]byte("abc azc a7c aac 888 a9c tac"), -1))  // ["abc" "azc" "a7c" "aac" "a9c"]
 fmt.Printf("%q\n", reg.FindAll([]byte("abc azc a7c aac 888 a9c tac"), 2))  // ["abc" "azc"]

方法 FindAllString

func (re *Regexp) FindAllString(s string, n int) []string

FindALl

方法 FindAllIndex

func (re *Regexp) FindAllIndex(b []byte, n int) [][]int

b 中的所有不重叠的、与 正则表达式 相匹配的结果的 起止位置的切片,只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项.

reg = regexp.MustCompile("a.c")
fmt.Println(reg.FindAllIndex([]byte("abc azc a7c aac 888 a9c tac"), 2)) // [[0 3] [4 7]]

方法 FindAllStringIndex

func (re *Regexp) FindAllStringIndex(s string, n int) [][]int

FindAllIndex

方法 FindAllSubmatch

func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte

类似 FindSubmatch 方法, FindSubmatch 是返回匹配的第一个的字符串 及 与子组匹配的字符串,只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项.:

 reg = regexp.MustCompile(`(a.c)([\w]+)`)
 fmt.Printf("%q\n", reg.FindAllSubmatch([]byte("abce azcea a7cx"), 2))  // [["abce" "abc" "e"] ["azcea" "azc" "ea"]]

方法 FindAllStringSubmatch

func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string

同 FindAllSubmatch

方法 FindAllSubmatchIndex

func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int

在 b 中查找 re 中编译好的正则表达式,并返回所有匹配的位置, 同时返回子表达式匹配的位置 ,只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项.

reg = regexp.MustCompile(`(a.c)([\w]+)`)// [[完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...], ]
fmt.Println( reg.FindAllSubmatchIndex([]byte("abce azcea a7cx"), 2))  // [[0 4 0 3 3 4] [5 10 5 8 8 10]]

方法 FindAllStringSubmatchIndex

func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int

FindAllSubmatchIndex

方法 Split

func (re *Regexp) Split(s string, n int) []string

Splitres 中匹配到的结果作为分隔符将 s 分割成多个字符串,并返回这些正则匹配结果之间的字符串的切片。 `
返回的切片不会包含正则匹配的结果

txt := "abcxxefgxxhijkxxlmnxx"
reg = regexp.MustCompile("xx")
fmt.Printf("%q\n", reg.Split(txt, -1))       //  ["abc" "efg" "hijk" "lmn" ""]

方法 Expand

func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte

template 的内容经过处理后,追加到 dst 的尾部。template 中要有 $1$2${name1}${name2} 这样的“分组引用符”;
match 是由 FindSubmatchIndex 方法返回的结果,里面存放了各个分组的位置信息;
如果 template 中有“分组引用符”,则以 match 为标准,在 src 中取出相应的子串,替换掉 template 中的 $1、$2 等引用符号。

reg = regexp.MustCompile(`(\w+),(\w+)`)
src := []byte("Golang,World!")     // 源文本
dst := []byte("Say: ")     // 目标文本
template := []byte("Hello $1, Hello $2")     // 模板
match := reg.FindSubmatchIndex(src)     // 解析源文本
fmt.Printf("%q\n", reg.Expand(dst, template, src, match))  // 填充模板,并将模板追加到目标文本中
// "Say: Hello Golang, Hello World"

正则可以写为: (?P\w+),(?P\w+), 然后模板应该为:Hello $n1, Hello $n2

方法 ExpandString

func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte

Expand

方法 ReplaceAllLiteral

func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte

在 src 中搜索匹配项,并替换为 repl 指定的内容,并返回替换后的结果.
如果 repl 中有 “分组引用符”($1$name),则将“分组引用符”当普通字符处理.

b := []byte("Hello World, 123 Go!")
reg = regexp.MustCompile(`(Hell|G)o`)
rep := []byte("${1}ooo")
fmt.Printf("%q\n", reg.ReplaceAllLiteral(b, rep))     // "${1}ooo World, 123 ${1}ooo!"

方法 ReplaceAllLiteral

func (re *Regexp) ReplaceAllLiteralString(src, repl string) string

ReplaceAllLiteral

方法 ReplaceAll

func (re *Regexp) ReplaceAll(src, repl []byte) []byte

src 中搜索匹配项,并替换为 repl 指定的内容, 全部替换,并返回替换后的结果.
如果 repl 中有 “分组引用符”($1$name),则将“分组引用符”替换为匹配到的相应的分组(会按照 Expand 方法的规则进行解释和替换).

b := []byte("Hello World, 123 Go!")
reg := regexp.MustCompile(`(Hell|G)o`)
rep := []byte("${1}ooo")
fmt.Printf("%q\n", reg.ReplaceAll(b, rep))        // "Hellooo World, 123 Gooo!"

方法 ReplaceAllString

func (re *Regexp) ReplaceAllString(src, repl string) string

ReplaceAll

方法 ReplaceAllFunc

func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte

src 中搜索匹配项,然后将匹配的内容作为 repl 的参数处理后,替换 src 中的匹配项;
如果 repl 的返回值中有“分组引用符”($1$name),则将“分组引用符”当普通字符处理;

s := []byte("Hello World!")
reg := regexp.MustCompile("(H)ello")
fmt.Printf("%s\n", reg.ReplaceAllFunc(s, func(b []byte) []byte {
    rst := []byte{}
    rst = append(rst, b...)
    rst = append(rst, []byte("$1")...)
    return rst
}))

方法 ReplaceAllStringFunc

func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string

ReplaceAllFunc

你可能感兴趣的:(go语言)