基本的字符串是否存在检测

在线运行open in new window启动 AI 助手open in new window

func main() {
	// a 和 b 中间
	matched, _ := regexp.MatchString(`a.b`, "aawbb")
	fmt.Println(matched) // true

	// 使用 ? 匹配 0 次或者 1 次
	matched, _ = regexp.MatchString(`a.?b`, "awb")
	fmt.Println(matched) // true

	// a 和 b 中间是数字
	matched, _ = regexp.MatchString(`a([0-9]+)b`, "a123b")
	fmt.Println(matched) // true

	// 使用了 + 匹配一次或者无限次
	matched, _ = regexp.MatchString(`^a.+b$`, "aawxxxbb")
	fmt.Println(matched) // true

	// 首尾限定
	matched, _ = regexp.MatchString(`^a.b$`, "awb")
	fmt.Println(matched) // true

	// 首尾限定并且 a 和 b 中间可以最多 1 个字符
	matched, _ = regexp.MatchString(`^a.?b$`, "awb")
	fmt.Println(matched) // true
}

第一个例子使用了点 . 符号,表示匹配任意字符,可以匹配 a 和 b 中间的任意一个字符。

第二个例子使用了问号 ? 符号,表示匹配前一个字符 0 次或者 1 次,因此可以匹配 a 和 b 中间没有字符或只有一个字符的情况。

第三个例子使用了中括号 [] 和加号 + 符号,表示匹配一个或多个数字。因此可以匹配 a 和 b 中间是一串数字的情况。

第四个例子使用了加号 + 符号,表示匹配前一个字符 1 次或多次,可以匹配 a 和 b 中间有多个字符的情况。

第五个例子使用了 ^ 和 $ 符号,表示限定匹配的字符串以 a 开头,以 b 结尾,中间是任意一个字符。

第六个例子在第五个例子的基础上使用了问号 ? 符号,表示匹配前一个字符 0 次或者 1 次,因此可以匹配 a 和 b 中间没有字符或只有一个字符的情况。

查找字符串

在线运行open in new window启动 AI 助手open in new window

func main() {
	re := regexp.MustCompile(`foo.?`)
	fmt.Printf("%q\n", re.FindString("seafood fool"))      // "food"
	fmt.Printf("%d\n", re.FindStringIndex("seafood fool")) // [3 7]

	re = regexp.MustCompile(`foo.*`)
	fmt.Printf("%q\n", re.FindString("seafood fool"))      // "food fool"
	fmt.Printf("%d\n", re.FindStringIndex("seafood fool")) // [3 12]

	re = regexp.MustCompile(`foo.+`)
	fmt.Printf("%q\n", re.FindString("seafood fool"))      // "food fool"
	fmt.Printf("%d\n", re.FindStringIndex("seafood fool")) // [3 12]

	fmt.Printf("%q\n", re.FindString("meat"))      // ""
	fmt.Printf("%d\n", re.FindStringIndex("meat")) // []
}

首先,使用 Regexp.MustCompile 函数编译了一个正则表达式 foo.?,然后调用 FindString 方法查找匹配的字符串,找到第一个匹配项 "food",输出结果为 "food",同时调用 FindStringIndex 方法也可以找到匹配项的起始和结束位置,输出结果为 [3 7]。

接下来,使用 Regexp.MustCompile 函数编译了一个正则表达式 foo.*,它使用了通配符 * 匹配前面的字符零次或多次,因此可以匹配到 "food" 和 "fool",输出结果为 "food fool",同时调用 FindStringIndex 方法也可以找到匹配项的起始和结束位置,输出结果为 [3 12]。

然后,使用 Regexp.MustCompile 函数编译了一个正则表达式 foo.+,它使用了通配符 + 匹配前面的字符一次或多次,因此可以匹配到 "food" 和 "fool",输出结果为 "food fool",同时调用 FindStringIndex 方法也可以找到匹配项的起始和结束位置,输出结果为 [3 12]。

最后,调用 FindString 和 FindStringIndex 方法查找字符串 "meat",由于该字符串没有匹配项,输出结果分别为 "" 和 []。

查找所有的匹配

在线运行open in new window启动 AI 助手open in new window

func main() {
	re := regexp.MustCompile(`a.`)
	fmt.Printf("%q\n", re.FindAllString("paranormal", -1)) // ["ar" "an" "al"]
	fmt.Printf("%q\n", re.FindAllString("paranormal", 2))  // ["ar" "an"]
	fmt.Printf("%q\n", re.FindAllString("graal", -1))      // ["aa"]
	fmt.Printf("%q\n", re.FindAllString("none", -1))       // []
}

代码首先通过 regexp.MustCompile 方法编译了一个正则表达式 a.,它表示一个字母 a 后面紧跟着任意一个字符。然后,它分别将字符串 "paranormal"、"graal" 和 "none" 作为参数传给 FindAllString 方法,并分别打印出返回的结果。

对于字符串 "paranormal",正则表达式 a. 匹配了三个子字符串 "ar"、"an" 和 "al",所以 FindAllString 返回了一个由这三个字符串组成的切片。由于第二个参数是 -1,所以返回所有匹配结果。

对于字符串 "graal",正则表达式 a. 只匹配了一个子字符串 "aa",所以 FindAllString 返回了一个只含有一个元素 "aa" 的切片。

对于字符串 "none",正则表达式 a. 没有匹配到任何子字符串,所以 FindAllString 返回了一个空的切片。

最后一个参数是限制返回匹配次数的参数。当这个参数大于 0 时,FindAllString 方法最多只返回给定数量的匹配结果。当这个参数为 0 或负数时,FindAllString 方法返回所有匹配结果。在这个例子中,第二个 FindAllString 方法将最多返回两个匹配结果。

替换匹配的字符串

在线运行open in new window启动 AI 助手open in new window

func main() {
	re := regexp.MustCompile(`ab*`)
	fmt.Printf("%q\n", re.ReplaceAllString("-a-abb-", "T")) // "-T-T-"

	re = regexp.MustCompile(`ab?`)
	fmt.Printf("%q\n", re.ReplaceAllString("-a-abb-", "T")) // "-T-Tb-"

	re = regexp.MustCompile(`ab+`)
	fmt.Printf("%q\n", re.ReplaceAllString("-a-abb-", "T")) // "-a-T-"
}

第一个正则表达式 ab* 匹配字符 a 后面跟着零个或多个 b。因此,它将 -a-abb- 中的 -a- 替换为 T,并将 -abb- 替换为 T,最终得到字符串 -T-T-。

第二个正则表达式 ab? 匹配字符 a 后面跟着零个或一个 b。因此,它将 -a-abb- 中的 -a- 替换为 T,并将 -ab- 替换为 T,但不替换 -b-。最终得到字符串 -T-Tb-。

第三个正则表达式 ab+ 匹配字符 a 后面跟着至少一个 b。因此,它将 -a-abb- 中的 -abb- 替换为 T,但不替换 -a- 或 -b-。最终得到字符串 -a-T-。

用匹配位置分割

在线运行open in new window启动 AI 助手open in new window

func main() {
	ra := regexp.MustCompile(`a`)
	fmt.Printf("%q\n", ra.Split("banana", -1)) // ["b" "n" "n" ""]
	fmt.Printf("%q\n", ra.Split("banana", 0))  // []
	fmt.Printf("%q\n", ra.Split("banana", 1))  // ["banana"]
	fmt.Printf("%q\n", ra.Split("banana", 2))  // ["b" "nana"]

	rz := regexp.MustCompile(`z+`)
	fmt.Printf("%q\n", rz.Split("pizza", -1)) // ["pi" "a"]
	fmt.Printf("%q\n", rz.Split("pizza", 0))  // []
	fmt.Printf("%q\n", rz.Split("pizza", 1))  // ["pizza"]
	fmt.Printf("%q\n", rz.Split("pizza", 2))  // ["pi" "a"]
}

Split 方法接受两个参数,第一个参数是待分割的字符串,第二个参数是分割后的子字符串的最大数量,如果传入 -1 则表示不限制最大数量。Split 方法会将字符串按照正则表达式进行分割,返回一个字符串切片。其中正则表达式中的匹配项将不会出现在切片中,而是用于匹配切片的分隔符。

在上面的代码中,首先使用 a 进行分割,将字符串 "banana" 分成了 ["b" "n" "n" ""] 四个子字符串。接着使用 z+ 进行分割,将字符串 "pizza" 分成了 ["pi" "a"] 两个子字符串。注意到对于传入 0 的情况,Split 方法会返回一个空切片。

Last Updated:
Contributors: Bob Wang