使用Go regex中的命名匹配项

Kur*_*ehr 32 regex go

我来自python,所以我可能只是没有以正确的方式看待它.我想创建一个相当复杂的正则表达式,并能够按名称访问字段匹配.我似乎无法找到一个好例子.我设法得到的最接近的是:

package main

import (
  "fmt"
  "regexp"
)

var myExp = regexp.MustCompile(`(?P<first>\d+)\.(\d+).(?P<second>\d+)`)

func main() {
  fmt.Printf("%+v", myExp.FindStringSubmatch("1234.5678.9"))

  match := myExp.FindStringSubmatch("1234.5678.9")
    for i, name := range myExp.SubexpNames() {
        fmt.Printf("'%s'\t %d -> %s\n", name, i, match[i])
    }
    //fmt.Printf("by name: %s %s\n", match["first"], match["second"])
}
Run Code Online (Sandbox Code Playgroud)

注释掉的行是我期望访问python中的命名字段的方式.什么是相同的方式来做到这一点?或者,如果我需要将匹配转换为地图,那么制作然后访问地图最常用的方法是什么?

hwn*_*wnd 44

您可以通过以下方式引用您的命名捕获组map:

package main

import (
    "fmt"
    "regexp"
)

var myExp = regexp.MustCompile(`(?P<first>\d+)\.(\d+).(?P<second>\d+)`)

func main() {
    match := myExp.FindStringSubmatch("1234.5678.9")
    result := make(map[string]string)
    for i, name := range myExp.SubexpNames() {
        if i != 0 && name != "" {
            result[name] = match[i]
        }
    }
    fmt.Printf("by name: %s %s\n", result["first"], result["second"])
}
Run Code Online (Sandbox Code Playgroud)

GoPlay

  • 还需要 `&amp;&amp; name != ""`(在 `i != 0` 之后),因此没有名称的捕获组不会进入地图。 (2认同)

gpa*_*nda 8

我没有评论的声誉,所以请原谅我,如果这不应该是一个'答案',但我发现上面的答案很有帮助,所以我把它包装成一个函数:

func reSubMatchMap(r *regexp.Regexp, str string) (map[string]string) {
    match := r.FindStringSubmatch(str)
    subMatchMap := make(map[string]string)
    for i, name := range r.SubexpNames() {
        if i != 0 {
            subMatchMap[name] = match[i]
        }
    }

    return subMatchMap
}
Run Code Online (Sandbox Code Playgroud)

Playground上的示例用法:https: //play.golang.org/p/LPLND6FnTXO

希望这对其他人有帮助.喜欢Go中命名捕获组的简易性.


rus*_*sst 8

当找不到“命名组”的匹配项时,其他方法将引发错误。

但是,以下内容map使用实际找到的任何命名组创建一个:

func findNamedMatches(regex *regexp.Regexp, str string) map[string]string {
    match := regex.FindStringSubmatch(str)

    results := map[string]string{}
    for i, name := range match {
        results[regex.SubexpNames()[i]] = name
    }
    return results
}
Run Code Online (Sandbox Code Playgroud)

这种方法只会返回具有命名组匹配的地图。如果没有匹配项,它只会返回nil。我发现如果没有找到匹配项,这比抛出错误要容易得多。