Golang每日一庫之regex

始識發表於2023-05-10

本文地址: https://www.cnblogs.com/zichliang/p/17387436.html
Golang日庫合集:https://www.cnblogs.com/zichliang/category/2297320.html

簡介

正規表示式是一種用來查詢、匹配或替換字串的技術。你可以使用它來找到符合特定模式的文字、刪除或替換匹配的字串。它可以用於各種程式語言和工具中,如Perl、Python、JavaScript、Java等等。
一句話概括就是,“正規表示式可以幫你快速、簡便地處理需要查詢、匹配或替換的文字內容,它可以大大提高程式的效率。”

正則介紹

正規表示式通常可以分為以下幾個步驟:

  1. 定義正規表示式模式:即給出需要匹配或查詢的文字規則,如匹配所有以"A"開頭的單詞,模式可以是 "^A\w+"。
  2. 編譯正規表示式:將正規表示式模式編譯成程式可識別的格式。
  3. 指定匹配文字:輸入需要進行匹配操作的文字,如一段英語文章。
  4. 進行匹配操作:程式會根據輸入的正規表示式和匹配文字進行匹配操作,搜尋所有與正規表示式模式匹配的子串。
  5. 獲取匹配結果:輸出匹配到的所有子串,包括位置、長度,或將它們替換成所需要的格式。

元字元
上文說的第一步與第二步匹配特定字元或字元型別的字元在正規表示式中具有特殊含義。一般來說,它們都是特殊符號或字母,用於匹配某個字元類或執行某種操作。
這裡就不列舉了
推薦個網站: 裡面包含了基本上所有的元字元: https://www.runoob.com/regexp/regexp-metachar.html

Golang中的正則

其實非常簡單主要分為三步

  1. 正則( 針對字串匹配規則)
  2. 元字元(基本上大同小異)
  3. 方法(特定語言有特定方法)

Golang 中常用的元字元:

  • .:匹配任意單個字元,除了換行符和回車符。
  • ^:匹配輸入字串的開始位置。
  • $:匹配輸入字串的結束位置。
  • *:匹配前面的字元(包括字元類)零次或多次。
  • +:匹配前面的字元(包括字元類)一次或多次。
  • ?:匹配前面的字元(包括字元類)零次或一次。
  • |:分隔兩個可選模式,匹配任意一個模式。
  • []:匹配其中的任意一個字元。可以使用短橫線表示範圍,如 [a-z] 表示匹配任意小寫字母。
  • \d:匹配任意一個數字字元,相當於 [0-9]。
  • \w:匹配任意一個字母、數字或下劃線,相當於 [a-zA-Z0-9_]。
  • \s:匹配任意一個空白字元,包括空格、製表符、換行符等。

Golang中的函式和方法介紹

在 Golang 中,標準庫 regexp 提供了一系列正則操作函式,下面是這些函式的簡要介紹:

  • Compile(expr string) (*Regexp, error):將一個字串編譯成一個正規表示式物件 Regexp。如果編譯失敗,會返回一個非 nil 的錯誤物件。
  • CompilePOSIX(expr string) (*Regexp, error):類似於 Compile 函式,但是將正規表示式解釋為 POSIX 語法。
  • MustCompile(expr string) *Regexp:類似於 Compile 函式,但是在編譯失敗時會直接丟擲一個 panic。
  • MustCompilePOSIX(expr string) *Regexp:類似於 MustCompile 函式,但是將正規表示式解釋為 POSIX 語法。
  • Match(pattern string, b []byte) (bool, error):判斷一個位元組陣列中是否包含指定的正規表示式。
  • MatchString(pattern string, s string) (bool, error):判斷一個字串中是否包含指定的正規表示式。
  • MatchReader(pattern string, r io.RuneReader) (bool, error):類似於 Match 函式,但是適用於 io.RuneReader 型別。
  • MatchRegexp(r *Regexp, s string) bool:對一個字串執行已編譯的正規表示式物件 Regexp 進行匹配。
  • MatchReaderRegexp(r *Regexp, r io.RuneReader) bool:類似於 MatchRegexp 函式,但是適用於 io.RuneReader 型別。
  • QuoteMeta(s string) string:將一個字串中的元字元以外的所有字元都轉義,使它們成為字面量。

除此之外,Regexp 物件還提供了一系列操作方法,例如:

  • Find(b []byte) []byte:返回第一個匹配的子字串。
  • FindAll(b []byte, n int) [][]byte:返回所有匹配的子字串,n 表示最大匹配次數。
  • FindAllIndex(b []byte, n int) [][]int:返回所有匹配的子字串的起止索引,n 表示最大匹配次數。
  • FindIndex(b []byte) (loc []int):返回第一個匹配的子字串的起止索引。
  • FindString(s string) string:返回第一個匹配的子字串。
  • FindAllString(s string, n int) []string:返回所有匹配的子字串,n 表示最大匹配次數。
  • FindAllStringIndex(s string, n int) [][]int:返回所有匹配的子字串的起止索引,n 表示最大匹配次數。
  • FindStringIndex(s string) (loc []int):返回第一個匹配的子字串的起止索引。
  • FindAllSubmatch(b []byte, n int) [][][]byte 返回的是位元組切片的切片的切片
  • FindAllSubmatchIndex(b []byte, n int) [][]int 返回所有匹配子串的開始和結束的字元索引位置。
  • FindAllStringSubmatch(s string, n int) [][]string 返回的是字串切片的切片的切片。
  • FindAllStringSubmatchIndex(s string, n int) [][]int 返回各個子串的開始和結束的索引值,
  • ReplaceAll(src []byte, repl []byte) []byte:將 src 中的所有匹配項替換為 repl,返回替換後的結果。
  • ReplaceAllString(src, repl string) string:類似於 ReplaceAll 函式,但是輸入輸出都是字串型別。
  • Split(s string, n int) []string:將 s 按照正規表示式分割,n 表示最大分割次數。
  • SplitN(s string, n int) []string:類似於 Split 函式,但是隻分割前 n 個子字串。

這些函式和方法可以滿足我們對正規表示式進行各種查詢、替換、分割等常見操作的需求。

Compile 和 MustCompile

在 Golang 中,我們可以使用 Compile 函式和 MustCompile 函式來將正規表示式字串編譯為一個 Regexp 物件。
這兩個函式的作用是相同的,都是將正規表示式字串編譯成一個正規表示式物件,只不過 MustCompile 函式在編譯失敗時會直接丟擲一個 panic。

Compile

// Compile 函式的使用方式
re, err := regexp.Compile(`\d+`)
if err != nil {
	// 正規表示式編譯失敗
	return
}
// 使用編譯後的正規表示式物件
fmt.Println(re.MatchString("123"))

結果

true

MustCompile

// MustCompile 函式的使用方式
re = regexp.MustCompile(`\d+`)
fmt.Println(re.MatchString("456"))

結果

true

FindAllSubmatch和FindAllStringSubmatch

FindAllSubmatch 方法是 Golang 中 Regexp 物件提供的一個方法。
用於在指定字串中查詢所有符合正規表示式規則的子字串,並返回子字串所對應的分組資訊及匹配位置。
其函式簽名如下:

func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string
func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int

FindAllSubmatch 和 FindAllStringSubmatch 方法都用於在字串中查詢所有匹配正規表示式的子字串,它們返回的是一個包含所有匹配子串和索引位置的二維切片。
FindAllStringSubmatchIndex 方法返回一個二維的整數切片,每個子切片表示一次匹配,每個子切片中的兩個整數分別表示匹配子串在源字串中的開始和結束位置的索引。
FindAllSubmatchIndex 方法也返回一個二維的整數切片,不同的是,每個子切片中都包含一系列整數,每兩個整數表示匹配的一組子表示式在源字串中的開始和結束位置的索引。

其中,re 是一個正規表示式物件,b 是需要查詢匹配的位元組切片,n 表示最大匹配次數,如果為 -1 則表示查詢所有匹配項。

返回值是一個二維切片,每個元素都是一個切片,包含所有匹配到的子串的位元組切片,以及子串出現的索引位置。

其實說的還是有些籠統

例子

package main

import (
	"fmt"
	"regexp"
	"strings"
)

func main() {
	content := `111 aba 1024 bbb 2048 ccc aba aba`
	pattern := `aba`
	compile, _ := regexp.Compile(pattern)
	results := compile.FindAllSubmatch([]byte(content), -1)
	fmt.Println(compile.FindAllSubmatchIndex([]byte(content), -1))
	for _, result := range results {
		fmt.Println("FindAllSubmatch>>>>>", result)
		fmt.Println("FindAllSubmatch>>>>>", result[0])
		fmt.Println("FindAllSubmatch>>>>>", string(result[0]))
	}
	fmt.Println(strings.Repeat("*", 100))
	results1 := compile.FindAllStringSubmatch(content, -1)
	fmt.Println(compile.FindAllStringSubmatchIndex(content, -1))
	for _, result := range results1 {
		fmt.Println("FindAllStringSubmatch>>>>>", result)
		fmt.Println("FindAllStringSubmatch>>>>>", result[0])
	}
}

結果如下:

例子2:

如果我們需要正則提取網站該如何實現呢?

package main

import (
	"fmt"
	"regexp"
	"strings"
)

func main() {
	content := `<a href="https://www.jd.com" target="_blank">京東</a> <a href="https://www.taobao.com" target="_blank">淘寶</a>`
	pattern := `<a href="(.*?)" target="_blank">(.*?)</a>`
	compile, _ := regexp.Compile(pattern)
	results := compile.FindAllSubmatch([]byte(content), -1)

	/*
		[][][]byte

		[]byte=""

		// 一旦加了括號等於分了組 後面會向這個切片追加值,所以下文只要切片取第二個值就行了 多分組就以此類推
		[
		[<a href="https://www.jd.com" target="_blank">京東</a>,https://www.jd.com,京東]
		[<a href="https://www.taobao.com" target="_blank">淘寶</a>,https://www.taobao.com,淘寶]
		]
	*/
	for _, result := range results {
		fmt.Println(strings.Repeat("*", 100))
		fmt.Println(string(result[0]), string(result[1]), string(result[2]))
	}

}

結果

本文地址: https://www.cnblogs.com/zichliang/p/17387436.html
Golang日庫合集:https://www.cnblogs.com/zichliang/category/2297320.html

相關文章