Golang:为什么regexp.FindAllStringSubmatch()返回[][]string而不是[]string?

4

我有些新手 go,并且这是我第一次处理正则表达式。

我有点惊讶,someregex.FindAllStringSubmatch("somestring", -1) 返回的是一个切片的切片 [][]string 而不是一个简单的字符串切片:[]string

例如:

someRegex, _ := regexp.Compile("^.*(mes).*$")
matches := someRegex.FindAllStringSubmatch("somestring", -1)
fmt.Println(matches) // logs [[somestring mes]]

这种行为的原因是什么,我想不出来?

1
因为它需要一个存储子匹配项的地方,即使用未转义括号对定义模式的组。 - Wiktor Stribiżew
你是什么意思? - n00dl3
1
你读过 https://golang.org/pkg/regexp/#Regexp.FindAllStringSubmatch 吗?你试过这个例子吗?你的正则表达式示例匹配整个字符串并捕获 mes。必须有一个地方用于匹配和捕获,对吧? - Wiktor Stribiżew
是的,我确实阅读了这个,但我没有想到尝试一下例子,现在更清晰了,谢谢。 - n00dl3
2个回答

8

func (*Regexp) FindAllStringSubmatch提取匹配和捕获子匹配。

子匹配是由一对未转义括号(所谓的捕获组)括起来的正则表达式部分匹配的文本部分。

在您的情况下,^.*(mes).*$匹配:

  • ^ - 字符串开始
  • .* - 任意0个或多个字符,尽可能多地匹配
  • (mes) - 捕获组1:一个mes子字符串
  • .*$ - 剩余的字符串。

因此,匹配值是整个字符串。它将成为输出中的第一个值。然后,由于有一个捕获组,结果中必须有一个位置,因此mes被放置在列表的第二个项目。

由于可能有多个匹配项,我们需要一个列表的列表。

更好的例子可能是具有多个匹配/子匹配提取(也可能是可选组)的例子:

package main

import (
    "fmt"
    "regexp"
)

func main() {
    someRegex, _ := regexp.Compile(`[^aouiye]([aouiye])([^aouiye])?`)
    matches := someRegex.FindAllStringSubmatch("somestri", -1)
    fmt.Printf("%q\n", matches)
}

[^aouiye]([aouiye])([^aouiye])?匹配一个非元音字母,一个元音字母,和一个非元音字母,并将后两个分别捕获到第1组和第2组中。

结果为[["som" "o" "m"] ["ri" "i" ""]]。共有2个匹配项,每个匹配项都包含一个匹配值、第1组值和第2组值。由于ri匹配没有文本被捕获到第2组(([^aouiye])?),所以它是空的,但它仍然存在,因为该组在正则表达式模式中被定义。


3
FindAllStringSubmatch是FindStringSubmatch的“全部”版本;它返回一个表达式所有连续匹配项的切片,如包注释中的“全部”描述所定义。返回值为nil表示没有匹配项。 文档
总之:您需要一个字符串数组的数组,因为这是FindStringSubmatch的全部版本。FindStringSubmatch将返回单个字符串数组。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接