Golang 正則表達式(regexp)

Go內置了(regexp包)對正則表達式的支持,這裏是一般的正則表達式常規用法的例子。

示例:

    package main

import (
    "bytes"
    "fmt"
    "regexp"
)

func main() {
    //是否匹配字符串
    // .匹配任意一個字符 ,*匹配零個或多個 ,優先匹配更多(貪婪)
    match, _ := regexp.MatchString("H(.*)d!", "Hello World!")
    fmt.Println(match) //true
    //或
    match, _ = regexp.Match("H(.*)d!", []byte("Hello World!"))
    fmt.Println(match) //true
    //或通過`Compile`來使用一個優化過的正則對象
    r, _ := regexp.Compile("H(.*)d!")
    fmt.Println(r.MatchString("Hello World!")) //true

    // 這個方法返回匹配的子串
    fmt.Println(r.FindString("Hello World! world")) //Hello World!
    //同上
    fmt.Println(string(r.Find([]byte("Hello World!")))) //Hello World!

    // 這個方法查找第一次匹配的索引
    // 的起始索引和結束索引,而不是匹配的字符串
    fmt.Println(r.FindStringIndex("Hello World! world")) //[0 12]

    // 這個方法返回全局匹配的字符串和局部匹配的字符,比如
    // 這裏會返回匹配`H(.*)d!`的字符串
    // 和匹配`(.*)`的字符串
    fmt.Println(r.FindStringSubmatch("Hello World! world")) //[Hello World! ello Worl]

    // 和上面的方法一樣,不同的是返回全局匹配和局部匹配的
    // 起始索引和結束索引
    fmt.Println(r.FindStringSubmatchIndex("Hello World! world")) //[0 12 1 10]
    // 這個方法返回所有正則匹配的字符,不僅僅是第一個
    fmt.Println(r.FindAllString("Hello World! Held! world", -1)) //[Hello World! Held!]

    // 這個方法返回所有全局匹配和局部匹配的字符串起始索引,只匹配最大的串
    // 和結束索引
    fmt.Println(r.FindAllStringSubmatchIndex("Hello World! world", -1))       //[[0 12 1 10]]
    fmt.Println(r.FindAllStringSubmatchIndex("Hello World! Held! world", -1)) //[[0 18 1 16]]

    // 爲這個方法提供一個正整數參數來限制匹配數量
    res, _ := regexp.Compile("H([a-z]+)d!")
    fmt.Println(res.FindAllString("Hello World! Held! Hellowrld! world", 2)) //[Held! Hellowrld!]

    fmt.Println(r.FindAllString("Hello World! Held! world", 2)) //[Hello World! Held!]
    //注意上面兩個不同,第二參數是一最大子串爲單位計算。

    // regexp包也可以用來將字符串的一部分替換爲其他的值
    fmt.Println(r.ReplaceAllString("Hello World! Held! world", "html")) //html world

    // `Func`變量可以讓你將所有匹配的字符串都經過該函數處理
    // 轉變爲所需要的值
    in := []byte("Hello World! Held! world")
    out := r.ReplaceAllFunc(in, bytes.ToUpper)
    fmt.Println(string(out))

    // 在 b 中查找 reg 中編譯好的正則表達式,並返回第一個匹配的位置
    // {起始位置, 結束位置}
    b := bytes.NewReader([]byte("Hello World!"))
    reg := regexp.MustCompile(`\w+`)
    fmt.Println(reg.FindReaderIndex(b)) //[0 5]

    // 在 字符串 中查找 r 中編譯好的正則表達式,並返回所有匹配的位置
    // {{起始位置, 結束位置}, {起始位置, 結束位置}, ...}
    // 只查找前 n 個匹配項,如果 n < 0,則查找所有匹配項

    fmt.Println(r.FindAllIndex([]byte("Hello World!"), -1)) //[[0 12]]
    //同上
    fmt.Println(r.FindAllStringIndex("Hello World!", -1)) //[[0 12]]

    // 在 s 中查找 re 中編譯好的正則表達式,並返回所有匹配的內容
    // 同時返回子表達式匹配的內容
    // {
    //     {完整匹配項, 子匹配項, 子匹配項, ...},
    //     {完整匹配項, 子匹配項, 子匹配項, ...},
    //     ...
    // }
    // 只查找前 n 個匹配項,如果 n < 0,則查找所有匹配項
    reg = regexp.MustCompile(`(\w)(\w)+`)                      //[[Hello H o] [World W d]]
    fmt.Println(reg.FindAllStringSubmatch("Hello World!", -1)) //[[Hello H o] [World W d]]

    // 將 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") // 模板
    m := reg.FindSubmatchIndex(src)          // 解析源文本
    // 填寫模板,並將模板追加到目標文本中
    fmt.Printf("%q", reg.Expand(dst, template, src, m))
    // "Say: Hello Golang, Hello World"

    // LiteralPrefix 返回所有匹配項都共同擁有的前綴(去除可變元素)
    // prefix:共同擁有的前綴
    // complete:如果 prefix 就是正則表達式本身,則返回 true,否則返回 false
    reg = regexp.MustCompile(`Hello[\w\s]+`)
    fmt.Println(reg.LiteralPrefix())
    // Hello false
    reg = regexp.MustCompile(`Hello`)
    fmt.Println(reg.LiteralPrefix())
    // Hello true

    text := `Hello World! hello world`
    // 正則標記“非貪婪模式”(?U)
    reg = regexp.MustCompile(`(?U)H[\w\s]+o`)
    fmt.Printf("%q\n", reg.FindString(text)) // Hello
    // 切換到“貪婪模式”
    reg.Longest()
    fmt.Printf("%q\n", reg.FindString(text)) // Hello Wo

    // 統計正則表達式中的分組個數(不包括“非捕獲的分組”)
    fmt.Println(r.NumSubexp()) //1

    //返回 r 中的“正則表達式”字符串
    fmt.Printf("%s\n", r.String())

    // 在 字符串 中搜索匹配項,並以匹配項爲分割符,將 字符串 分割成多個子串
    // 最多分割出 n 個子串,第 n 個子串不再進行分割
    // 如果 n < 0,則分割所有子串
    // 返回分割後的子串列表
    fmt.Printf("%q\n", r.Split("Hello World! Helld! hello", -1)) //["" " hello"]

    // 在 字符串 中搜索匹配項,並替換爲 repl 指定的內容
    // 如果 rep 中有“分組引用符”($1、$name),則將“分組引用符”當普通字符處理
    // 全部替換,並返回替換後的結果
    s := "Hello World, hello!"
    reg = regexp.MustCompile(`(Hell|h)o`)
    rep := "${1}"
    fmt.Printf("%q\n", reg.ReplaceAllLiteralString(s, rep)) //"${1} World, hello!"

    // 在 字符串 中搜索匹配項,然後將匹配的內容經過 repl 處理後,替換 字符串 中的匹配項
    // 如果 repb 的返回值中有“分組引用符”($1、$name),則將“分組引用符”當普通字符處理
    // 全部替換,並返回替換後的結果
    ss := []byte("Hello World!")
    reg = regexp.MustCompile("(H)ello")
    repb := []byte("$0$1")
    fmt.Printf("%s\n", reg.ReplaceAll(ss, repb))
    // HelloH World!

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

}

小結:

1、

r, _ := regexp.Compile("H(.*)d!")

可用一下代替

r := regexp.MustCompile("H(.*)d!")

兩者區別 MustCompile 少一個返回值err

看源碼

// Compile parses a regular expression and returns, if successful,
// a Regexp object that can be used to match against text.
//...
// For POSIX leftmost-longest matching, see CompilePOSIX.
func Compile(expr string) (*Regexp, error) {
    return compile(expr, syntax.Perl, false)
}

// MustCompile is like Compile but panics if the expression cannot be parsed.
// It simplifies safe initialization of global variables holding compiled regular
// expressions.
func MustCompile(str string) *Regexp {
   regexp, err := Compile(str)
   if err != nil {
      panic(`regexp: Compile(` + quote(str) + `): ` + err.Error())
   }
   return regexp
}

2、regexp的處理byte的方法都有個string方法對應,兩者功能一樣。

例如:

regexp.Match()
和
regexp.MatchString()

links

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章