1. 程式人生 > 程式設計 >Go語言正則表示式的使用詳解

Go語言正則表示式的使用詳解

正則表示式是一種進行模式匹配和文字操縱的功能強大的工具。正則表示式靈活、易用,按照它的語法規則,隨需構造出的匹配模式就能夠從原始文字中篩選出幾乎任何你想要得到的字元組合。

準則

  • 預設是最短匹配,只要字串滿足條件就返回。
  • 如果沒有匹配到,都是返回為nil。
  • 如果需要做最長匹配,呼叫Longest()函式。
  • 正則表示式功能:匹配(macth),查詢(find)和替換(replace)。
  • 存在長度選擇的函式,傳入<0的數字表示匹配全部。

使用regexp呼叫

Match,MatchReader和 MatchString

// 判斷b中是夠包含pattern能夠組成的任意字串
func Match(pattern string,b []byte) (matched bool,err error)

// 判斷reader r中返回的字串是否包含pattern能夠組成的任意字串
func MatchReader(pattern string,r io.RuneReader) (matched bool,err error)

// 判斷字串s中是否包含pattern能夠組成的任意字串
func MatchString(pattern string,s string) (matched bool,err error)

Compile 和 MushCompile

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

Compile :返回Regexp 物件,方便呼叫指標函式。

MustCompile :同Compile,解析表示式失敗,會panic。

在匹配文字時,該正則表示式會盡可能早的開始匹配,並且在匹配過程中選擇回溯搜尋到的第一個匹配結果。這種模式被稱為leftmost-first ,另外一般情況下使用MustCompile 即可。

使用regexp.Regexp物件來呼叫

Find 和 FindAll

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

Find返回保管正則表示式re在b中的最左側的一個匹配結果的[]byte切片。如果沒有匹配到,會返回nil,最多匹配一個。

re := regexp.MustCompile(`foo.?`)
fmt.Printf("%q\n",re.Find([]byte(`seafood fool`)))
re := regexp.MustCompile(`foo.?`)
fmt.Printf("%q\n",re.FindAll([]byte(`seafood fool`),-1))

FindAll 功能與Find 一樣,只是返回全部滿足條件的資料。

FindString 和 FindAllString

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

與Find 和FindAll 一樣,只是針對字串string操作。

FindIndex 和 FindAllIndex

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

FindIndex , 返回b 中滿足匹配字串部分的起始位置,同樣是**“leftmost-first”**原則,loc包含起止位置。如果沒有找到,直接返回nil 。

FindAllIndex ,功能和FindIndex 保持一致,只是匹配多個,n 決定了匹配的位置。

FindStringIndex 和 FindAllStringIndex

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

與FindIndex 和FindAllIndex 使用方式類似,只是針對的是字串string。

FindStringSubmatch 和 FindAllStringSubmatch

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

FindStringSubmatch :採用左匹配原則,最多匹配一個,如果沒有的話,返回nil 。對於返回的[]string,分別標示匹配的字串,子串。

re := regexp.MustCompile(`a(x*)b(y|z)c`)
fmt.Printf("%q\n",re.FindStringSubmatch("-axxxbyc-"))
fmt.Printf("%q\n",re.FindStringSubmatch("-abzc-"))

輸出結果:

["axxxbyc" "xxx" "y"]
["abzc" "" "z"]

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

和FindStringSubmatch 使用類似,只是能顧選擇匹配的長度,-1 表示匹配到末尾。

re := regexp.MustCompile(`a(x*)b`)
fmt.Printf("%q\n",re.FindAllStringSubmatch("-ab-",-1))
fmt.Printf("%q\n",re.FindAllStringSubmatch("-axxb-",re.FindAllStringSubmatch("-ab-axb-",re.FindAllStringSubmatch("-axxb-ab-",-1))

輸出結果:

[["ab" ""]]
[["axxb" "xx"]]
[["ab" ""] ["axb" "x"]]
[["axxb" "xx"] ["ab" ""]]

FindSubmatchIndex 和 FindAllSubmatchIndex

  • func (re *Regexp) FindSubmatchIndex(b []byte) []int
  • func (re *Regexp) FindAllSubmatchIndex(b []byte,n int) [][]int 計運算元串在源串中的位置,已經存在(x*) 等返回結果處理,如果沒有返回nil 。

另外,index 返回為左閉右開 的模式,示例中的2,2 表示空字串的意思。 並且,不會存在重合匹配的,比如說"-axxb-ab-"去匹配a(x*)b ,不會存在第一個a 和最後一個b 結合的情況,如果使用Longest 就會匹配最長的。

re := regexp.MustCompile(`a(x*)b`)
// Indices:
// 01234567 012345678
// -ab-axb- -axxb-ab-
fmt.Println(re.FindAllStringSubmatchIndex("-ab-",-1))
fmt.Println(re.FindAllStringSubmatchIndex("-axxb-",-1))
fmt.Println(re.FindAllStringSubmatchIndex("-ab-axb-",-1))
fmt.Println(re.FindAllStringSubmatchIndex("-axxb-ab-",-1))
fmt.Println(re.FindAllStringSubmatchIndex("-foo-",-1))

輸出結果:

[[1 3 2 2]] // 2 2 表示為空
[[1 5 2 4]]
[[1 3 2 2] [4 7 5 6]]
[[1 5 2 4] [6 8 7 7]]
[]


FindStringSubmatchIndex 和 FindAllStringSubmatchIndex
func (re *Regexp) FindStringSubmatchIndex(s string) []int
func (re *Regexp) FindAllStringSubmatchIndex(s string,n int) [][]int
和 FindSubmatchIndex , FindAllSubmatchIndex 保持一致。

Longest
func (re *Regexp) Longest() 獲取最長匹配的滿足條件的內容。
re := regexp.MustCompile(`a(|b)`)
fmt.Println(re.FindString("ab"))
re.Longest()
fmt.Println(re.FindString("ab"))

輸出結果:

a
ab

下面這種情況不會最長匹配。

re := regexp.MustCompile(`a(x*)b`)
re.Longest()
fmt.Println(re.FindString("-axxb-ab-")) // axxb,不會存在第一個a和最後一個b組合的過程。

Match,MatchString和MatchReader

  • func (re *Regexp) Match(b []byte) bool
  • func (re *Regexp) MatchString(s string) bool
  • func (re *Regexp) MatchReader(r io.RuneReader) bool

判斷b ,s 和r 返回的資料是否滿足正則表示式,返回true 或者false 。

NumSubexp

  • func (re *Regexp) NumSubexp() int

返回分組的數量。

re0 := regexp.MustCompile(`a.`)
fmt.Printf("%d\n",re0.NumSubexp())

re := regexp.MustCompile(`(.*)((a)b)(.*)a`)
fmt.Println(re.NumSubexp())

輸出結果:

0
4

ReplaceAll 和 ReplaceAllString
func (re *Regexp) ReplaceAll(src,repl []byte) []byte
func (re *Regexp) ReplaceAllString(src,repl string) string
ReplaceAllString 與 ReplaceAll 使用方式相同。

re := regexp.MustCompile(`a(x*)b`)
fmt.Printf("%s\n",re.ReplaceAll([]byte("-ab-axxb-"),[]byte("T"))) 
fmt.Printf("%s\n",[]byte("$1"))) // $1表示匹配的第一個子串,這是ab的中間無字串,所以$1為空,然後使用空去替換滿足正則表示式的部分。
fmt.Printf("%s\n",[]byte("$1W"))) // "$1W"等價與"$(1W)",值為空,將滿足條件的部分完全替換為空。
fmt.Printf("%s\n",[]byte("${1}W"))) // ${1}匹配(x*),保留。輸出-W-xxW-

輸出結果:

-T-T-
--xx-
---
-W-xxW-

s := "Hello World,123 Go!"
//定義一個正則表示式reg,匹配Hello或者Go
reg := regexp.MustCompile(`(Hell|G)o`)

s2 := "2019-12-01,test"
//定義一個正則表示式reg2,匹配 YYYY-MM-DD 的日期格式
reg2 := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)

//最簡單的情況,用“T替換”"-ab-axxb-"中符合正則"a(x*)b"的部分
reg3 := regexp.MustCompile("a(x*)b")
fmt.Println(re.ReplaceAllString("-ab-axxb-","T")) // -T-T-

//${1}匹配"Hello World,123 Go!"中符合正則`(Hell|G)`的部分並保留,去掉"Hello"與"Go"中的'o'並用"ddd"追加
rep1 := "${1}ddd"
fmt.Printf("%q\n",reg.ReplaceAllString(s,rep1)) // Hellddd World,123 Gddd!

//首先,"2019-12-01,test"中符合正則表示式`(\d{4})-(\d{2})-(\d{2})`的部分是"2019-12-01",將該部分匹配'(\d{4})'的'2019'保留,去掉剩餘部分
rep2 := "${1}"
fmt.Printf("%q\n",reg2.ReplaceAllString(s2,rep2)) // 2019,test

//首先,"2019-12-01,將該部分匹配'(\d{2})'的'12'保留,去掉剩餘部分
 rep3 := "${2}"
fmt.Printf("%q\n",rep3)) // 12,將該部分匹配'(\d{2})'的'01'保留,去掉剩餘部分,並追加"13:30:12"
rep4 := "${3}:13:30:12"
fmt.Printf("%q\n",rep4)) // 01:13:30:12,test
}

ReplaceAllFunc 和 ReplaceAllStringFunc

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

將匹配出來滿足條件的[]byte 作為引數傳入函式中。

re := regexp.MustCompile(`[^aeiou]`)
fmt.Println(re.ReplaceAllStringFunc("seafood fool",strings.ToUpper))

兩者使用方式類似。

ReplaceAllLiteral 和 ReplaceAllLiteralString

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

匹配字面常量,不轉換。

re := regexp.MustCompile(`a(x*)b`)
fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-","T"))
fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-","$1"))
fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-","${1}"))

輸出結果:

-T-T-
-$1-$1-
-${1}-${1}-

關於$1 說明:

Go語言正則表示式的使用詳解
Go語言正則表示式的使用詳解

Expand 和 ExpandString

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

Expand返回新生成的將template新增到dst後面的切片。在新增時,Expand會將template中的變數替換為從src匹配的結果。match應該是被FindSubmatchIndex返回的匹配結果起止位置索引。(通常就是匹配src,除非你要將匹配得到的位置用於另一個[]byte)

在template引數裡,一個變量表示為格式如:$name 或${name} 的字串,其中name是長度>0的字母、數字和下劃線的序列。一個單純的數字字元名如$1會作為捕獲分組的數字索引;其他的名字對應(?P...)語法產生的命名捕獲分組的名字。超出範圍的數字索引、索引對應的分組未匹配到文字、正則表示式中未出現的分組名,都會被替換為空切片。

$name格式的變數名,name會盡可能取最長序列:$1x 等價於${1x} 而非${1}x ,$10 等價於${10} 而非${1}0 。因此$name 適用在後跟空格/換行等字元的情況,${name} 適用所有情況。

如果要在輸出中插入一個字面值'$' ,在template裡可以使用$$ 。

其他示例

解析網址

flysnowRegexp := regexp.MustCompile(`^http://www.flysnow.org/([\d]{4})/([\d]{2})/([\d]{2})/([\w-]+).html$`)
params := flysnowRegexp.FindStringSubmatch("http://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html")
// 返回[]string{}資料型別
for _,param := range params {
 fmt.Println(param)
}

輸出結果:

http://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html
2018
01
20
golang-goquery-examples-selector

總結

到此這篇關於Go語言正則表示式的使用詳解的文章就介紹到這了,更多相關Go正則表示式使用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!