Golang Regexp.FindAllStringSubmatchIndex
最后修改于 2025 年 4 月 20 日
本教程将介绍如何在 Go 中使用 Regexp.FindAllStringSubmatchIndex
方法。我们将涵盖其功能并提供实际示例。
一个 正则表达式 是一个定义搜索模式的字符序列。它用于在字符串中进行模式匹配。
Regexp.FindAllStringSubmatchIndex
方法返回一个索引切片,用于标识正则表达式的最左匹配项。它同时提供匹配项和子匹配项的位置。
基本的 FindAllStringSubmatchIndex 示例
此示例展示了 FindAllStringSubmatchIndex
的最简单用法。我们在字符串中查找简单模式的所有匹配项。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`\d+`) str := "I have 3 apples and 5 oranges" indices := re.FindAllStringSubmatchIndex(str, -1) fmt.Println(indices) for _, match := range indices { fmt.Println("Match:", str[match[0]:match[1]]) } }
该方法返回一个整数切片的切片。每个内部切片包含成对的索引,表示匹配位置。这里我们查找所有数字序列。
提取子匹配项索引
此示例演示了如何获取匹配项和子匹配项的索引。我们将日期字符串解析为各个部分。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`) str := "2025-04-20 and 2026-05-21 are important dates" indices := re.FindAllStringSubmatchIndex(str, -1) for _, match := range indices { fmt.Println("Full match:", str[match[0]:match[1]]) fmt.Println("Year:", str[match[2]:match[3]]) fmt.Println("Month:", str[match[4]:match[5]]) fmt.Println("Day:", str[match[6]:match[7]]) } }
索引在开始和结束位置之间交替。整个匹配项位于 0-1,随后是成对的子匹配项。这使我们能够提取匹配项的特定部分。
查找重叠匹配项
此示例展示了如何在字符串中查找重叠匹配项。我们查找所有可能的 3 个字母的序列。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?=(\w{3}))`) str := "Golang" indices := re.FindAllStringSubmatchIndex(str, -1) for _, match := range indices { fmt.Println(str[match[2]:match[3]]) } }
前瞻断言 (?=...)
允许查找重叠匹配项。每个匹配项显示输入字符串中不同的 3 个字符序列。
提取键值对
这里我们从字符串解析键值对,并使用索引提取它们。这对于配置解析很有用。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(\w+)=("[^"]*"|\S+)`) str := `name="John Doe" age=30 city="New York"` indices := re.FindAllStringSubmatchIndex(str, -1) for _, match := range indices { key := str[match[2]:match[3]] value := str[match[4]:match[5]] fmt.Printf("Key: %s, Value: %s\n", key, value) } }
该模式匹配键(单词字符)和值(带引号的字符串或非空格序列)。索引有助于精确提取这些部分。
查找 HTML 标签属性
此示例演示了提取 HTML 标签属性及其确切位置。我们解析一个锚标签的 href 和 title。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`Link` indices := re.FindAllStringSubmatchIndex(str, -1) if len(indices) > 0 { match := indices[0] fmt.Println("Full tag:", str[match[0]:match[1]]) fmt.Println("Href:", str[match[2]:match[3]]) fmt.Println("Title:", str[match[4]:match[5]]) } }
该正则表达式匹配一个带有 href 和 title 属性的锚标签。索引使我们能够提取这些属性及其在原始字符串中的确切位置。
处理多个匹配项
此示例展示了在更长的文本中处理多个匹配项。我们查找所有电子邮件地址及其位置。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})`) str := `Contact us at info@example.com or support@company.co.uk for help.` indices := re.FindAllStringSubmatchIndex(str, -1) for i, match := range indices { fmt.Printf("Match %d:\n", i+1) fmt.Println(" Full email:", str[match[0]:match[1]]) fmt.Println(" Username:", str[match[2]:match[3]]) fmt.Println(" Domain:", str[match[4]:match[5]]) fmt.Println(" Position:", match[0], "-", match[1]) } }
该方法查找文本中的所有电子邮件地址。对于每个电子邮件地址,我们获取完整的电子邮件、用户名、域及其在原始字符串中的确切位置。
带有命名捕获组的复杂模式
这个高级示例使用命名捕获组并处理结果。我们解析带有时间戳和严重性级别的日志条目。
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<time>\d{2}:\d{2}:\d{2}) (?P<level>\w+): (?P<message>.*)`) str := `10:30:45 ERROR: File not found 11:15:22 WARNING: Disk space low 12:01:33 INFO: Backup completed` indices := re.FindAllStringSubmatchIndex(str, -1) names := re.SubexpNames() for _, match := range indices { for i, name := range names { if i != 0 && name != "" { start := match[2*i] end := match[2*i+1] fmt.Printf("%s: %s\n", name, str[start:end]) } } fmt.Println() } }
命名捕获组使代码更具可读性。我们使用 SubexpNames
将组索引映射到名称,然后使用匹配索引提取值。
来源
本教程通过模式匹配和带位置信息的文本处理的实际示例,介绍了 Go 中的 Regexp.FindAllStringSubmatchIndex
方法。