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 方法。