Golang Regexp.FindAllSubmatchIndex
最后修改于 2025 年 4 月 20 日
本教程将介绍如何在 Go 语言中使用 Regexp.FindAllSubmatchIndex
方法。我们将涵盖其功能并提供实际示例。
一个 正则表达式 是一个定义搜索模式的字符序列。它用于在字符串中进行模式匹配。
Regexp.FindAllSubmatchIndex
方法返回一个整数切片组成的切片。每个整数切片代表匹配项和子匹配项的位置。
基本的 FindAllSubmatchIndex 示例
FindAllSubmatchIndex
最简单的用法是查找字符串中的所有匹配项及其位置。这里我们定位简单的单词匹配。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`go`) text := "go golang go go" indices := re.FindAllSubmatchIndex([]byte(text), -1) for _, match := range indices { fmt.Printf("Found at %d-%d: %s\n", match[0], match[1], text[match[0]:match[1]]) } }
我们编译模式 "go",并在文本中查找所有出现的地方。每次匹配都会返回输入字节切片中的开始和结束位置。
查找子匹配项的位置
此示例演示了捕获组的位置。我们将提取日期组件及其确切位置。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`) text := "Date: 2025-04-20, Another: 2026-05-21" matches := re.FindAllSubmatchIndex([]byte(text), -1) for _, match := range matches { fmt.Println("Full match:", text[match[0]:match[1]]) fmt.Println("Year:", text[match[2]:match[3]]) fmt.Println("Month:", text[match[4]:match[5]]) fmt.Println("Day:", text[match[6]:match[7]]) } }
该模式有三个捕获组。每次匹配都会返回八个整数:完整匹配项以及每个组的开始/结束位置对。
查找重叠匹配项
使用先行断言时,FindAllSubmatchIndex
可以查找重叠匹配项。这显示了所有可能的 3 位数字序列。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?=(\d{3}))`) text := "12345" matches := re.FindAllSubmatchIndex([]byte(text), -1) for _, match := range matches { start, end := match[2], match[3] fmt.Printf("Found at %d-%d: %s\n", start, end, text[start:end]) } }
先行断言会查找后面跟着三个数字的所有位置。每次匹配都会返回先行断言的位置和捕获的组。
提取键值对
此示例展示了如何解析键值对并获取其确切位置。我们将处理一个简单的配置文件字符串。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(\w+)=("[^"]*"|\S+)`) text := `name="John Doe" age=30 city="New York"` matches := re.FindAllSubmatchIndex([]byte(text), -1) for _, match := range matches { key := text[match[2]:match[3]] value := text[match[4]:match[5]] fmt.Printf("Key: %s (at %d-%d), Value: %s (at %d-%d)\n", key, match[2], match[3], value, match[4], match[5]) } }
该模式匹配键和值,支持带引号的值。我们提取每个组件的内容和位置。
查找嵌套结构
这个高级示例演示了如何解析嵌套结构。我们将提取 HTML 标签及其属性和位置。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`<(\w+)(\s+([^>]*))?>`) text := `<div class="header"><p align="center">Hello</p></div>` matches := re.FindAllSubmatchIndex([]byte(text), -1) for _, match := range matches { fmt.Println("Full tag:", text[match[0]:match[1]]) fmt.Println("Tag name:", text[match[2]:match[3]]) if match[4] != -1 { fmt.Println("Attributes:", text[match[6]:match[7]]) } } }
该模式匹配带有可选属性的 HTML 标签。我们检查 -1 以处理未参与匹配的可选组。
处理空匹配
此示例展示了 FindAllSubmatchIndex
如何处理空匹配。我们将处理可能包含零长度匹配项的字符串。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`a*`) text := "baaab" matches := re.FindAllSubmatchIndex([]byte(text), -1) for i, match := range matches { if match[0] == match[1] { fmt.Printf("Match %d: empty at position %d\n", i, match[0]) } else { fmt.Printf("Match %d: %q at %d-%d\n", i, text[match[0]:match[1]], match[0], match[1]) } } }
该模式匹配零个或多个 'a'。空匹配会返回相等的开始和结束位置。此行为对于某些算法很重要。
性能注意事项
在处理大型文本时,请考虑限制匹配的数量。此示例说明了如何控制结果的大小。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`\d+`) text := "1 22 333 4444 55555 666666" // Find first 3 matches matches := re.FindAllSubmatchIndex([]byte(text), 3) for _, match := range matches { fmt.Println(text[match[0]:match[1]]) } }
第二个参数限制了返回的匹配数量。使用此参数可以防止可能多次匹配的模式导致过多的内存使用。
来源
本教程通过查找匹配项及其位置的实际示例,介绍了 Go 语言中的 Regexp.FindAllSubmatchIndex
方法。