regex 如何在GoLang中使用捕获组?

juzqafwq  于 2023-06-30  发布在  Go
关注(0)|答案(1)|浏览(119)

我需要使用正则表达式获取Golang日志,但是正则表达式的输出对于“msg”捕获组是不正确的。我在这里使用这个函数从文件的内容中提取日志语句:

func extractLogStatements(content string) []LogStatement {
    logPattern := `flog\.(?P<sev>.*?)\(\s*flog.(?P<type>.*?),\s*("|fmt.Sprintf\(")(?P<msg>.*?)"`

    re := regexp.MustCompile(logPattern)
    matches := re.FindAllStringSubmatch(content, -1)

    logStatements := make([]LogStatement, 0, len(matches))
    for _, match := range matches {
        statement := LogStatement{
            Sev:  match[1],
            Type: match[2],
            Msg:  match[3],
        }
        logStatements = append(logStatements, statement)
    }

    return logStatements
}

除了函数第一行的正则表达式模式没有为捕获组捕获正确的值之外,其他一切都正常工作,尽管我在在线正则表达式解析器上测试时它工作得很好。
下面是我测试过的一些日志示例:

flog.Info(flog.Application, fmt.Sprintf("unable to translate address for config: %v", err))

flog.Info(flog.Application, "unable to translate address for config")

flog.Info(flog.Application, fmt.Sprintf("Test 1"),
    lm.CrKind, objectType,
    lm.CrName, crName,
    lm.AppNS, namespace)

对于第一个日志示例,它应该提取“Info”(“sev”捕获组)、“Application”(“type”捕获组)和“unable to translate address for config:%v”(“msg”捕获组)。当我输出到json时,我得到:

[
    {
        "sev": "Info",
        "type": "Application",
        "msg": "fmt.Sprintf(\""
    },
    {
        "sev": "Info",
        "type": "Application",
        "msg": "fmt.Sprintf(\""
    },
    {
        "sev": "Info",
        "type": "Application",
        "msg": "fmt.Sprintf(\""
    },
]

因此,它正确地捕获了“sev”和“type”捕获组,但对于“msg”,它捕获了“fmt.sprintf(”“当它应该获得“无法转换config的地址:%v”。

hfyxw5xn

hfyxw5xn1#

match[3]存储组("|fmt.Sprintf\(")的值。如果你不想捕获它,可以使用?:将它变成一个非捕获组。

(?:"|fmt.Sprintf\(")

由于所有你想要的值都是通过命名的捕获组捕获的,另一种解决方案是通过名称引用它们:

for _, match := range matches {
    statement := LogStatement{
        Sev:  match[re.SubexpIndex("sev")],
        Type: match[re.SubexpIndex("type")],
        Msg:  match[re.SubexpIndex("msg")],
    }
    logStatements = append(logStatements, statement)
}

相关问题