猿问

如何从 regexp.ReplaceAllFunc 访问捕获组?

如何从 ReplaceAllFunc() 内部访问捕获组?


package main


import (

    "fmt"

    "regexp"

)


func main() {

    body := []byte("Visit this page: [PageName]")

    search := regexp.MustCompile("\\[([a-zA-Z]+)\\]")


    body = search.ReplaceAllFunc(body, func(s []byte) []byte {

        // How can I access the capture group here?

    })


    fmt.Println(string(body))

}

目标是替换[PageName]为<a href="/view/PageName">PageName</a>.


这是编写 Web 应用程序Go 教程底部“其他任务”部分下的最后一个任务。


汪汪一只猫
浏览 205回答 3
3回答

holdtom

我同意在您的函数内部访问捕获组是理想的,我认为regexp.ReplaceAllFunc. 现在我想到的唯一关于如何使用该函数执行此操作的是:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "regexp")func main() {&nbsp; &nbsp; body := []byte("Visit this page: [PageName] [OtherPageName]")&nbsp; &nbsp; search := regexp.MustCompile("\\[[a-zA-Z]+\\]")&nbsp; &nbsp; body = search.ReplaceAllFunc(body, func(s []byte) []byte {&nbsp; &nbsp; &nbsp; &nbsp; m := string(s[1 : len(s)-1])&nbsp; &nbsp; &nbsp; &nbsp; return []byte("<a href=\"/view/" + m + "\">" + m + "</a>")&nbsp; &nbsp; })&nbsp; &nbsp; fmt.Println(string(body))}编辑还有另一种方式我知道如何做你想做的事。您需要知道的第一件事是您可以使用正则表达式(?:re)where reis 的语法指定非捕获组。这不是必需的,但会减少不感兴趣的匹配的数量。接下来要知道的是regexp.FindAllSubmatcheIndex。它将返回切片的切片,其中每个内部切片代表给定正则表达式匹配的所有子匹配的范围。有了这两件事,您就可以构建一些通用的解决方案:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "regexp")func ReplaceAllSubmatchFunc(re *regexp.Regexp, b []byte, f func(s []byte) []byte) []byte {&nbsp; &nbsp; idxs := re.FindAllSubmatchIndex(b, -1)&nbsp; &nbsp; if len(idxs) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; return b&nbsp; &nbsp; }&nbsp; &nbsp; l := len(idxs)&nbsp; &nbsp; ret := append([]byte{}, b[:idxs[0][0]]...)&nbsp; &nbsp; for i, pair := range idxs {&nbsp; &nbsp; &nbsp; &nbsp; // replace internal submatch with result of user supplied function&nbsp; &nbsp; &nbsp; &nbsp; ret = append(ret, f(b[pair[2]:pair[3]])...)&nbsp; &nbsp; &nbsp; &nbsp; if i+1 < l {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = append(ret, b[pair[1]:idxs[i+1][0]]...)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; ret = append(ret, b[idxs[len(idxs)-1][1]:]...)&nbsp; &nbsp; return ret}func main() {&nbsp; &nbsp; body := []byte("Visit this page: [PageName] [OtherPageName][XYZ]&nbsp; &nbsp; &nbsp;[XY]")&nbsp; &nbsp; search := regexp.MustCompile("(?:\\[)([a-zA-Z]+)(?:\\])")&nbsp; &nbsp; body = ReplaceAllSubmatchFunc(search, body, func(s []byte) []byte {&nbsp; &nbsp; &nbsp; &nbsp; m := string(s)&nbsp; &nbsp; &nbsp; &nbsp; return []byte("<a href=\"/view/" + m + "\">" + m + "</a>")&nbsp; &nbsp; })&nbsp; &nbsp; fmt.Println(string(body))}

智慧大石

如果你想得到 group in ReplaceAllFunc,你可以使用ReplaceAllStringget 子组。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "regexp")func main() {&nbsp; &nbsp; body := []byte("Visit this page: [PageName]")&nbsp; &nbsp; search := regexp.MustCompile("\\[([a-zA-Z]+)\\]")&nbsp; &nbsp; body = search.ReplaceAllFunc(body, func(s []byte) []byte {&nbsp; &nbsp; &nbsp; &nbsp; // How can I access the capture group here?&nbsp; &nbsp; &nbsp; &nbsp; group := search.ReplaceAllString(string(s), `$1`)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(group)&nbsp; &nbsp; &nbsp; &nbsp; // handle group as you wish&nbsp; &nbsp; &nbsp; &nbsp; newGroup := "<a href='/view/" + group + "'>" + group + "</a>"&nbsp; &nbsp; &nbsp; &nbsp; return []byte(newGroup)&nbsp; &nbsp; })&nbsp; &nbsp; fmt.Println(string(body))}当有很多组时,你可以通过这种方式获取每个组,然后处理每个组并返回所需的值。

慕森王

您必须ReplaceAllFunc先在FindStringSubmatch同一个正则表达式的函数调用中再次调用。喜欢:func (p parser) substituteEnvVars(data []byte) ([]byte, error) {&nbsp; &nbsp; var err error&nbsp; &nbsp; substituted := p.envVarPattern.ReplaceAllFunc(data, func(matched []byte) []byte {&nbsp; &nbsp; &nbsp; &nbsp; varName := p.envVarPattern.FindStringSubmatch(string(matched))[1]&nbsp; &nbsp; &nbsp; &nbsp; value := os.Getenv(varName)&nbsp; &nbsp; &nbsp; &nbsp; if len(value) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Printf("Fatal error substituting environment variable %s\n", varName)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return []byte(value)&nbsp; &nbsp; });&nbsp; &nbsp; return substituted, err}
随时随地看视频慕课网APP

相关分类

Go
我要回答