2022年5月30日 星期一

Go 開發筆記 - 使用 Regular Expression / Regex / Re

網路上還滿多教學以及文件,其中官方文件 pkg.go.dev/regexp 滿清楚的。也有看到一篇許多人推的 github.com/StefanSchroeder/Golang-Regex-Tutorial ,有中英文。

在此把一些語法筆記一下,方便自己未來快速回憶。

使用筆記:
  • 有兩種 Regular Expression 實現方式 ,其中有 POSIX 關鍵字是 POSIX ERE (egrep) 語法跟效果。
  • 初始化有 Compile 跟 MustCompile (對應的是 CompilePOSIX 和 MustCompilePOSIX) ,其中有 Must 字眼是驗證語法錯誤時,會進入 panics 狀態
使用範例:

% cat main.go
package main

// https://pkg.go.dev/regexp
// https://pkg.go.dev/regexp/syntax

import (
    "fmt"
    "regexp"
)

func main() {
    input := `
<html>
    <head>
        <title>study golang</title>
    </head>
    <body>
        <ul>
            <li>changyy.org</li>
            <li>1234567890</li>
            <li>abcdefg</li>
            <li>abcdefgABCDEFG</li>
            <li>abcdef1234567890gABCDEFG</li>
        </ul>
    </body>
</html>`

    // Style 1: regexp.Match
    {
        matched, err := regexp.Match(`<[A-Za-z]+>(.*?)</[A-Za-z]+>`, []byte(input))
        if err != nil {
            fmt.Println("Style 1 - regexp.Match error:", err)
        } else {
            fmt.Println("Style 1 - regexp.Match: ", matched)
        }
    }

    // Style 2: regexp.Compile + obj.MatchString
    // https://pkg.go.dev/regexp#Regexp.MatchString
    {
        obj, err := regexp.Compile(`<[A-Za-z]+>(.*?)</[A-Za-z]+>`)
        if err != nil {
            fmt.Println("regexp.Compile error:", err)
        } else {
            fmt.Println("Style 2 - case 1: ", obj.MatchString(`<title>Hello World</title>`))
            fmt.Println("Style 2 - case 2: ", obj.MatchString(input))
        }
    }

    // Style 3: regexp.MustCompile + obj.MatchString
    // https://pkg.go.dev/regexp#Regexp.MatchString
    {
        pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 3 - case 1: ", obj.MatchString(`<title>Hello World</title>`))
        fmt.Println("Style 3 - case 2: ", obj.MatchString(input))
    }

    // Style 4: obj.FindString
    // https://pkg.go.dev/regexp#Regexp.FindString
    {
        pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 4 - case 1: ", obj.FindString(`<title>Hello World</title>`))
        fmt.Println("Style 4 - case 2: ", obj.FindString(input))
    }

    // Style 5: obj.FindAllString , obj.FindAllStringIndex
    // https://pkg.go.dev/regexp#Regexp.FindAllString
    // https://pkg.go.dev/regexp#Regexp.FindAllStringIndex
    {
        pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 5 - case 1: ", obj.FindAllString(`<title>Hello World</title>`, -1))
        fmt.Println("Style 5 - case 2: ", obj.FindAllString(input, -1))
        fmt.Println("Style 5 - case 3: ", obj.FindAllStringIndex(`<title>Hello World</title>`, -1))
        fmt.Println("Style 5 - case 4: ", obj.FindAllStringIndex(input, -1))
    }

    // Style 6: obj.FindStringSubmatch , obj.FindStringSubmatchIndex
    // https://pkg.go.dev/regexp#Regexp.FindStringSubmatch
    // https://pkg.go.dev/regexp#Regexp.FindStringSubmatchIndex
    {
        pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 6 - case 1: ", obj.FindStringSubmatch(`<title>Hello World</title>`))
        fmt.Println("Style 6 - case 2: ", obj.FindStringSubmatch(input))
        fmt.Println("Style 6 - case 3: ", obj.FindStringSubmatchIndex(`<title>Hello World</title>`))
        fmt.Println("Style 6 - case 4: ", obj.FindStringSubmatchIndex(input))
    }

    // Style 7: obj.ReplaceAllString
    // https://pkg.go.dev/regexp#Regexp.ReplaceAllString
    {
        pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 7 - case 1: ", obj.ReplaceAllString(`<title>Hello World</title>`, "A"))
        fmt.Println("Style 7 - case 2: ", obj.ReplaceAllString(input, "B"))
    }

    // Style 8: obj.Split
    // https://pkg.go.dev/regexp#Regexp.Split
    {
        pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 8 - case 1: ", len(obj.Split(`<title>Hello World</title>`, -1)))
        fmt.Println("Style 8 - case 2: ", len(obj.Split(input, -1)))
    }

    // Style 9: obj.Longest()
    // https://pkg.go.dev/regexp#Regexp.FindString
    // https://pkg.go.dev/regexp#Regexp.Longest
    {
        pattern := `a(|b)`
        obj := regexp.MustCompile(pattern)
        fmt.Println("Style 9 - case 1: ", obj.FindString(`abb`))
        obj.Longest()
        fmt.Println("Style 9 - case 2: ", obj.FindString(`abb`))
    }
}

% go run main.go 
Style 1 - regexp.Match:  true
Style 2 - case 1:  true
Style 2 - case 2:  true
Style 3 - case 1:  true
Style 3 - case 2:  true
Style 4 - case 1:  <title>Hello World</title>
Style 4 - case 2:  <title>study golang</title>
Style 5 - case 1:  [<title>Hello World</title>]
Style 5 - case 2:  [<title>study golang</title> <li>changyy.org</li> <li>1234567890</li> <li>abcdefg</li> <li>abcdefgABCDEFG</li> <li>abcdef1234567890gABCDEFG</li>]
Style 5 - case 3:  [[0 26]]
Style 5 - case 4:  [[27 54] [103 123] [136 155] [168 184] [197 220] [233 266]]
Style 6 - case 1:  [<title>Hello World</title> Hello World]
Style 6 - case 2:  [<title>study golang</title> study golang]
Style 6 - case 3:  [0 26 7 18]
Style 6 - case 4:  [27 54 34 46]
Style 7 - case 1:  A
Style 7 - case 2:  
<html>
    <head>
        B
    </head>
    <body>
        <ul>
            B
            B
            B
            B
            B
        </ul>
    </body>
</html>
Style 8 - case 1:  2
Style 8 - case 2:  7
Style 9 - case 1:  a
Style 9 - case 2:  ab

沒有留言:

張貼留言