1. 程式人生 > >golang 正則匹配regexp介面實戰學習

golang 正則匹配regexp介面實戰學習

總覽

如果不熟悉正則表示式的語法的話,可以執行下面命令:

go doc regexp/syntax

聯絡程式碼

package main

import (
    "fmt"
    "regexp"
)

func expandTest() {
    pat := `(((abc.)def.)ghi)`
    reg := regexp.MustCompile(pat)
    fmt.Println(reg.NumSubexp())

    src := []byte(`abc-def-ghi abc+def+ghi`)
    template := []byte(`$0
$1 $2 $3`) // 替換第一次匹配結果 match := reg.FindSubmatchIndex(src) fmt.Printf("%v\n", match) // [0 11 0 11 0 8 0 4] dst := reg.Expand(nil, template, src, match) fmt.Printf("%s\n\n", dst) // abc-def-ghi abc-def-ghi abc-def- abc- // 替換所有匹配結果 for _, match := range reg.FindAllSubmatchIndex
(src, -1) { fmt.Printf("%v\n", match) dst := reg.Expand(nil, template, src, match) fmt.Printf("%s\n", dst) } // [0 11 0 11 0 8 0 4] // abc-def-ghi abc-def-ghi abc-def- abc- // [12 23 12 23 12 20 12 16] // abc+def+ghi abc+def+ghi abc+def+ abc+ } func testFind() { re := regexp.MustCompile
("a*r") fmt.Println(string(re.Find([]byte("paranoabrmal")))) fmt.Println(re.NumSubexp()) rep := regexp.MustCompilePOSIX("a*r|ara") fmt.Println(string(rep.Find([]byte("paranoabrmal")))) fmt.Println(rep.NumSubexp()) b := []byte("abc1def1") pat := `abc1|abc1def1` reg1 := regexp.MustCompile(pat) // 第一匹配 reg2 := regexp.MustCompilePOSIX(pat) // 最長匹配 fmt.Printf("%s\n", reg1.Find(b)) // abc1 fmt.Printf("%s\n", reg2.Find(b)) // abc1def1 fmt.Println(reg1.NumSubexp()) b = []byte("abc1def1") pat = `(abc|abc1def)*1` reg1 = regexp.MustCompile(pat) // 第一匹配 reg2 = regexp.MustCompilePOSIX(pat) // 最長匹配 fmt.Printf("%s\n", reg1.Find(b)) // abc1 fmt.Printf("%s\n", reg2.Find(b)) // abc1def1 fmt.Println(reg1.NumSubexp()) } func testFindAll() { re := regexp.MustCompile("ar") fmt.Printf("%q\n", (re.FindAll([]byte("paranoarmal"), -1))) rep := regexp.MustCompilePOSIX("ar") fmt.Printf("%q\n", (rep.FindAll([]byte("paranoarmal"), -1))) pat := `(((abc.)def.)ghi)` src := []byte(`abc-def-ghi abc+def+ghi`) reg := regexp.MustCompile(pat) fmt.Printf("%q\n", (reg.Find(src))) fmt.Printf("%q\n", (reg.FindAll(src, -1))) regp := regexp.MustCompilePOSIX(pat) fmt.Printf("%q\n", (regp.Find(src))) fmt.Printf("%q\n", (regp.FindAll(src, -1))) } func testReg(pat, srcStr string) { fmt.Println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") src := []byte(srcStr) reg := regexp.MustCompile(pat) fmt.Printf("%q\n", (reg.Find(src))) fmt.Printf("%q\n", (reg.FindString(srcStr))) fmt.Printf("%q\n", (reg.FindAll(src, -1))) fmt.Printf("%q\n", (reg.FindAllString(srcStr, -1))) fmt.Printf("%d\n", (reg.FindIndex(src))) fmt.Printf("%d\n", (reg.FindStringIndex(srcStr))) fmt.Printf("%d\n", (reg.FindAllIndex(src, -1))) fmt.Printf("%d\n", (reg.FindAllStringIndex(srcStr, -1))) fmt.Println("begin submatch") fmt.Printf("%q\n", (reg.FindSubmatch(src))) fmt.Printf("%q\n", (reg.FindStringSubmatch(srcStr))) fmt.Printf("%d\n", (reg.FindSubmatchIndex(src))) fmt.Printf("%d\n", (reg.FindStringSubmatchIndex(srcStr))) fmt.Printf("%q\n", (reg.FindAllSubmatch(src, -1))) fmt.Printf("%q\n", (reg.FindAllStringSubmatch(srcStr, -1))) fmt.Printf("%d\n", (reg.FindAllSubmatchIndex(src, -1))) fmt.Printf("%d\n", (reg.FindAllStringSubmatchIndex(srcStr, -1))) regp := regexp.MustCompilePOSIX(pat) fmt.Printf("%q\n", (regp.Find(src))) fmt.Printf("%q\n", (regp.FindString(srcStr))) fmt.Printf("%q\n", (regp.FindAll(src, -1))) fmt.Printf("%q\n", (regp.FindAllString(srcStr, -1))) fmt.Printf("%d\n", (regp.FindIndex(src))) fmt.Printf("%d\n", (regp.FindStringIndex(srcStr))) fmt.Printf("%d\n", (regp.FindAllIndex(src, -1))) fmt.Printf("%d\n", (regp.FindAllStringIndex(srcStr, -1))) fmt.Println("begin submatch") fmt.Printf("%q\n", (regp.FindSubmatch(src))) fmt.Printf("%q\n", (regp.FindStringSubmatch(srcStr))) fmt.Printf("%q\n", (regp.FindAllSubmatch(src, -1))) fmt.Printf("%q\n", (regp.FindAllStringSubmatch(srcStr, -1))) fmt.Printf("%d\n", (regp.FindSubmatchIndex(src))) fmt.Printf("%d\n", (regp.FindStringSubmatchIndex(srcStr))) fmt.Printf("%d\n", (regp.FindAllSubmatchIndex(src, -1))) fmt.Printf("%d\n", (regp.FindAllStringSubmatchIndex(srcStr, -1))) } func main() { testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`) testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`) testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`) testReg(`a*r`, `paranoabrmal`) }

程式碼詳解

Find FindString

fmt.Printf("%q\n", (reg.Find(src)))
fmt.Printf("%q\n", (reg.FindString(srcStr)))

Find返回leftmost的正則匹配結果,也就是滿足匹配的最左邊的最短匹配字串

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:"abc-def-ghixx"
分析:*表示0或多個,優先選擇多個,所以優先匹配為"abc-def-ghixx"

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:"abc-def-ghi"
分析:滿足匹配項的的最左的最短匹配就是"abc-def-ghi"

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:"axxxbyc"
分析:滿足匹配項的的最左的最短匹配就是"abc-def-ghi"

testReg(`a*r`, `paranoabrmal`)
結果:"ar"
分析:滿足匹配項的的最左的最短匹配就是"ar"

FindAll FIndAllString

fmt.Printf("%q\n", (reg.FindAll(src, -1)))
fmt.Printf("%q\n", (reg.FindAllString(srcStr, -1)))

FindAll是Find的“ALL”版本,返回相鄰的非互相覆蓋的最短匹配項

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:["abc-def-ghixx" "abc+def+ghixx"]
分析:返回所有匹配項

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:["abc-def-ghi" "abc+def+ghi"]
分析:返回所有匹配項

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:["axxxbyc" "abzc"]
分析:返回所有匹配項

testReg(`a*r`, `paranoabrmal`)
結果:["ar" "r"]
分析:*表示0或多個,所以第二個就僅僅匹配了r

FindIndex FindStringIndex

fmt.Printf("%d\n", (reg.FindIndex(src)))
fmt.Printf("%d\n", (reg.FindStringIndex(srcStr)))

FindIndex是Find的“Index”版本,匹配項在原字串中的位置,返回nil標示沒有找到匹配項。

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:[0 13]
分析:`abc-def-ghixxa abc+def+ghixx`[0:13]就是"abc-def-ghixx"

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:[0 11]
分析:同上

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:[1 8]
分析:同上

testReg(`a*r`, `paranoabrmal`)
結果:[1 3]
分析:同上

FindAllIndex FindAllStringIndex

fmt.Printf("%d\n", (reg.FindAllIndex(src, -1)))
fmt.Printf("%d\n", (reg.FindAllStringIndex(srcStr, -1)))

FindAllIndex是FindAll的“Index”版本,標示匹配項在原字串中的位置,返回nil標示沒有找到匹配項。

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:[[0 13] [15 28]]
分析:`abc-def-ghixxa abc+def+ghixx`[0:13]就是"abc-def-ghixx"
        `abc-def-ghixxa abc+def+ghixx`[15:28]就是"abc+def+ghixx"

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:[[0 11] [15 26]]
分析:同上

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:[[1 8] [11 15]]
分析:同上

testReg(`a*r`, `paranoabrmal`)
結果:[[1 3] [8 9]]
分析:同上

FindSubmatch FindStringSubmatch

fmt.Printf("%q\n", (reg.FindSubmatch(src)))
fmt.Printf("%q\n", (reg.FindStringSubmatch(srcStr)))

FindSubmatch是Find的“Submatch”版本,這個版本返回正則表示式的子匹配項。子匹配指的是在括號內的子正則表示式,從左到右進行標號。
子匹配0標示全部的表示式,子匹配1標示第1個括號內的子表示式,以此類推。

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:["abc-def-ghixx" "abc-def-ghi" "abc-def-" "abc-"]
分析:“.”匹配任意字元。submatch0為 `(((abc.)def.)ghi)x*`,submatch1為`(((abc.)def.)ghi)`,submatch2為`((abc.)def.)`,submatch3為`(abc.)`,

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:["abc-def-ghi" "abc-def-ghi" "abc-def-" "abc-"]
分析:“.”匹配任意字元。submatch0為 `(((abc.)def.)ghi)`,submatch1為`(((abc.)def.)ghi)`,submatch2為`((abc.)def.)`,submatch3為`(abc.)`,

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:["axxxbyc" "xxx" "y"]
分析:submatch0為`a(x*)b(y|z)c`,submatch1為`(x*)`,submatch2為`(y|z)`

testReg(`a*r`, `paranoabrmal`)
結果:["ar"]
分析:submatch0為`a*r`

FindSubmatchIndex FindStringSubmatchIndex

fmt.Printf("%d\n", (reg.FindSubmatchIndex(src)))
fmt.Printf("%d\n", (reg.FindStringSubmatchIndex(srcStr)))

FindSubmatchIndex是FindSubmatch的Index版本,返回匹配項的首尾下標

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:[0 13 0 11 0 8 0 4]
分析: `abc-def-ghixxa abc+def+ghixx`[0:13]="abc-def-ghixx"
        `abc-def-ghixxa abc+def+ghixx`[0:11]="abc-def-ghi"
        `abc-def-ghixxa abc+def+ghixx`[0:8]= "abc-def-"
        `abc-def-ghixxa abc+def+ghixx`[0:4]="abc-"

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:[0 11 0 11 0 8 0 4]
分析:同上

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:[1 8 2 5 6 7]
分析:同上

testReg(`a*r`, `paranoabrmal`)
結果:[1 3]
分析:同上

FindAllSubmatch FindAllStringSubmatch

fmt.Printf("%q\n", (reg.FindAllSubmatch(src, -1)))
fmt.Printf("%q\n", (reg.FindAllStringSubmatch(srcStr, -1)))

FindAllSubmatch是FindSubmatch的“All”版本,這個版本返回全部匹配項的子匹配項。
子匹配0標示全部的表示式,子匹配1標示第1個括號內的子表示式,以此類推。

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:[["abc-def-ghixx" "abc-def-ghi" "abc-def-" "abc-"] ["abc+def+ghixx" "abc+def+ghi" "abc+def+" "abc+"]]
分析:參考FindSubmatch

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:[["abc-def-ghi" "abc-def-ghi" "abc-def-" "abc-"] ["abc+def+ghi" "abc+def+ghi" "abc+def+" "abc+"]]
分析:參考FindSubmatch


testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:[["axxxbyc" "xxx" "y"] ["abzc" "" "z"]]
分析:參考FindSubmatch


testReg(`a*r`, `paranoabrmal`)
結果:[["ar"] ["r"]]
分析:參考FindSubmatch

FindAllSubmatchIndex FindAllStringSubmatchIndex

fmt.Printf("%d\n", (reg.FindAllSubmatchIndex(src, -1)))
fmt.Printf("%d\n", (reg.FindAllStringSubmatchIndex(srcStr, -1)))

FindAllSubmatchIndex是FindAllSubmatch的Index版本,返回匹配項的首尾下標

testReg(`(((abc.)def.)ghi)x*`, `abc-def-ghixxa abc+def+ghixx`)
結果:[[0 13 0 11 0 8 0 4] [15 28 15 26 15 23 15 19]]
分析: 參考FindSubmatchIndex

testReg(`(((abc.)def.)ghi)`, `abc-def-ghixxa abc+def+ghixx`)
結果:[[0 11 0 11 0 8 0 4] [15 26 15 26 15 23 15 19]]
分析: 參考FindSubmatchIndex

testReg(`a(x*)b(y|z)c`, `-axxxbyc- -abzc-`)
結果:[[1 8 2 5 6 7] [11 15 12 12 13 14]]
分析: 參考FindSubmatchIndex

testReg(`a*r`, `paranoabrmal`)
結果:[[1 3] [8 9]]
分析: 參考FindSubmatchIndex

測試程式碼參考了這篇文章