How to access capture group from regexp.ReplaceAllFunc?

How can I access the capture group from within 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))
}

The goal is to replace [PageName]with <a href="/view/PageName">PageName</a>.

This is the last task in the Other Tasks section at the bottom of Writing Web Applications . Textbook.

+4
source share
2 answers

I agree that access to the capture group inside your function would be ideal, I don't think this is possible with regexp.ReplaceAllFunc. The only thing that comes to my mind right now is how to do this with this function:

package main

import (
    "fmt"
    "regexp"
)

func main() {
    body := []byte("Visit this page: [PageName] [OtherPageName]")
    search := regexp.MustCompile("\\[[a-zA-Z]+\\]")
    body = search.ReplaceAllFunc(body, func(s []byte) []byte {
        m := string(s[1 : len(s)-1])
        return []byte("<a href=\"/view/" + m + "\">" + m + "</a>")
    })
    fmt.Println(string(body))
}

EDIT

, , , . , , (?:re), re - . , .

, , regexp.FindAllSubmatcheIndex. , all .

, :

package main

import (
    "fmt"
    "regexp"
)

func ReplaceAllSubmatchFunc(re *regexp.Regexp, b []byte, f func(s []byte) []byte) []byte {
    idxs := re.FindAllSubmatchIndex(b, -1)
    if len(idxs) == 0 {
        return b
    }
    l := len(idxs)
    ret := append([]byte{}, b[:idxs[0][0]]...)
    for i, pair := range idxs {
        // replace internal submatch with result of user supplied function
        ret = append(ret, f(b[pair[2]:pair[3]])...)
        if i+1 < l {
            ret = append(ret, b[pair[1]:idxs[i+1][0]]...)
        }
    }
    ret = append(ret, b[idxs[len(idxs)-1][1]:]...)
    return ret
}

func main() {
    body := []byte("Visit this page: [PageName] [OtherPageName][XYZ]     [XY]")
    search := regexp.MustCompile("(?:\\[)([a-zA-Z]+)(?:\\])")

    body = ReplaceAllSubmatchFunc(search, body, func(s []byte) []byte {
        m := string(s)
        return []byte("<a href=\"/view/" + m + "\">" + m + "</a>")
    })

    fmt.Println(string(body))
}
+4

ReplaceAllFunc FindStringSubmatch . :

func (p parser) substituteEnvVars(data []byte) ([]byte, error) {
    var err error
    substituted := p.envVarPattern.ReplaceAllFunc(data, func(matched []byte) []byte {
        varName := p.envVarPattern.FindStringSubmatch(string(matched))[1]
        value := os.Getenv(varName)
        if len(value) == 0 {
            log.Printf("Fatal error substituting environment variable %s\n", varName)
        }

        return []byte(value)
    });
    return substituted, err
}
0

All Articles