ZetCode

Golang Regexp.FindStringIndex

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 Go 中使用 Regexp.FindStringIndex 方法。我们将介绍它的用途并提供实际的用法示例。

一个 正则表达式 是一个定义搜索模式的字符序列。它用于在字符串中进行模式匹配。

Regexp.FindStringIndex 方法返回一个由两个整数组成的切片,定义了字符串中最左边匹配项的位置。第一个元素是起始索引,第二个元素是结束索引。

基本的 FindStringIndex 示例

FindStringIndex 最简单的用法是查找单词的位置。这里我们定位“world”的第一次出现。

basic_find.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`world`)
    str := "hello world, welcome to the world of Go"
    
    indices := re.FindStringIndex(str)
    fmt.Println(indices) // [6 11]
    
    if indices != nil {
        fmt.Println("Found at:", indices[0], "to", indices[1])
        fmt.Println("Matched:", str[indices[0]:indices[1]])
    }
}

该方法返回 [6 11],表示匹配从索引 6 开始到索引 11 结束。如果没有找到匹配项,则返回 nil。我们可以使用这些索引来切片字符串。

查找多个出现

要查找所有出现次数,我们使用 FindAllStringIndex。此示例查找所有“go”匹配项(不区分大小写)。

multiple_find.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(?i)go`)
    str := "Go to the GO store and buy golang GO"
    
    allIndices := re.FindAllStringIndex(str, -1)
    for i, loc := range allIndices {
        fmt.Printf("Match %d: %v, text: %s\n", 
            i+1, loc, str[loc[0]:loc[1]])
    }
}

(?i) 使匹配不区分大小写。我们获得了四个匹配项及其位置。第二个参数(-1)表示查找所有匹配项。

使用子匹配项查找索引

此示例显示了如何获取捕获组的索引。我们解析日期字符串。

submatch_indices.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
    date := "Event date: 2025-04-20"
    
    // Get indices for full match and submatches
    indices := re.FindStringSubmatchIndex(date)
    if indices != nil {
        fmt.Println("Full match:", indices[0:2])
        fmt.Println("Year:", indices[2:4], date[indices[2]:indices[3]])
        fmt.Println("Month:", indices[4:6], date[indices[4]:indices[5]])
        fmt.Println("Day:", indices[6:8], date[indices[6]:indices[7]])
    }
}

FindStringSubmatchIndex 为每个捕获组返回索引对。偶数索引是起始位置,奇数索引是匹配的结束位置。

查找第一个数字的索引

此示例查找字符串中第一个数字的位置。它演示了简单的模式匹配。

first_digit.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\d`)
    str := "Product ID: A42B-789C"
    
    loc := re.FindStringIndex(str)
    if loc != nil {
        fmt.Println("First digit at position:", loc[0])
        fmt.Println("Digit is:", str[loc[0]:loc[1]])
    } else {
        fmt.Println("No digits found")
    }
}

模式 \d 匹配任何数字。该方法返回第一个匹配项的位置(在此示例中为 14)。然后我们可以提取该数字。

在文本中查找 URL 索引

此示例查找文本块中的所有 HTTP/HTTPS URL。它展示了一个更复杂的带索引的模式。

url_finder.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`https?://[^\s]+`)
    text := `Visit https://example.com or http://test.org for more info.`
    
    urls := re.FindAllStringIndex(text, -1)
    for _, loc := range urls {
        fmt.Printf("URL found at %v: %s\n", 
            loc, text[loc[0]:loc[1]])
    }
}

该模式匹配 http:// 或 https:// 后跟非空白字符。我们获取文本中两个 URL 的确切位置以进行进一步处理。

验证和提取电子邮件位置

此示例验证电子邮件并显示其位置。它结合了匹配和索引提取。

email_positions.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b`)
    text := `Contact us at info@example.com or support@company.co.uk`
    
    emails := re.FindAllStringIndex(text, -1)
    for i, loc := range emails {
        fmt.Printf("Email %d: %s (positions %d-%d)\n",
            i+1, text[loc[0]:loc[1]], loc[0], loc[1])
    }
}

该模式匹配标准的电子邮件格式。我们获取电子邮件地址及其在输入字符串中的确切位置,用于验证或提取。

查找重叠匹配项

这个高级示例演示了如何通过手动调整搜索位置来查找重叠匹配项。我们在“banana”中查找所有“ana”。

overlapping.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`ana`)
    str := "banana"
    pos := 0
    
    for pos < len(str) {
        loc := re.FindStringIndex(str[pos:])
        if loc == nil {
            break
        }
        actualStart := pos + loc[0]
        actualEnd := pos + loc[1]
        
        fmt.Printf("Found at %d-%d: %s\n",
            actualStart, actualEnd, str[actualStart:actualEnd])
        
        pos += loc[0] + 1 // Move just past current match start
    }
}

通过搜索子字符串和调整位置,我们找到了所有匹配项,包括重叠的匹配项。这项技术对于某些模式匹配任务很有用。

来源

Go regexp 包文档

本教程通过使用正则表达式查找字符串位置的实际示例,涵盖了 Go 中的 Regexp.FindStringIndex 方法。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程