如何在Golang正则表达式中替换all参数?

时间:2016-06-20 10:04:15

标签: regex go

我正在使用Golang regex包,我想使用regex ReplaceAllStringFunc和参数,而不仅仅是源字符串。

例如,我想更新此文本

"<img src=\"/m/1.jpg\" />  <img src=\"/m/2.jpg\" />  <img src=\"/m/3.jpg\" />"

要(将“m”改为“a”或其他任何东西):

"<img src=\"/a/1.jpg\" />  <img src=\"/a/2.jpg\" />  <img src=\"/a/3.jpg\" />"

我希望有类似的东西:

func UpdateText(text string) string {
    re, _ := regexp.Compile(`<img.*?src=\"(.*?)\"`)
    text = re.ReplaceAllStringFunc(text, updateImgSrc) 
    return text
}

// update "/m/1.jpg" to "/a/1.jpg" 
func updateImgSrc(imgSrcText, prefix string) string {
    // replace "m" by prefix
    return "<img src=\"" + newImgSrc + "\""
}

我检查了文档,ReplaceAllStringFunc不支持参数,但实现目标的最佳方法是什么?

更一般地说,我想找到一个模式的所有匹配项,然后使用由源字符串+新参数组成的新字符串更新每个模式,是否有人可以提出任何想法?

2 个答案:

答案 0 :(得分:2)

我同意这些评论,你可能不想用正则表达式解析HTML(会发生不好的事情)。

但是,我们假装它不是HTML,并且您只想替换子匹配。你可以这样做

func UpdateText(input string) (string, error) {
    re, err := regexp.Compile(`img.*?src=\"(.*?)\.(.*?)\"`)
    if err != nil {
        return "", err
    }
    indexes := re.FindAllStringSubmatchIndex(input, -1)

    output := input
    for _, match := range indexes {
        imgStart := match[2]
        imgEnd := match[3]
        newImgName := strings.Replace(input[imgStart:imgEnd], "m", "a", -1)
        output = output[:imgStart] + newImgName + input[imgEnd:]
    }
    return output, nil
}

see on playground

(请注意,我稍微更改了您的正则表达式以分别匹配文件扩展名)

答案 1 :(得分:1)

感谢kostix的建议,这是我使用html解析器的解决方案。

func UpdateAllResourcePath(text, prefix string) (string, error) {
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(text))
    if err != nil {
        return "", err
    }

    sel := doc.Find("img")
    length := len(sel.Nodes)
    for index := 0; index < length; index++ {
        imgSrc, ok := sel.Eq(index).Attr("src")
        if !ok {
            continue
        }

        newImgSrc, err := UpdateResourcePath(imgSrc, prefix)    // change the imgsrc here
        if err != nil {
            return "", err
        }

        sel.Eq(index).SetAttr("src", newImgSrc)
    }

    newtext, err := doc.Find("body").Html()
    if err != nil {
        return "", err
    }

    return newtext, nil
}