我正在使用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不支持参数,但实现目标的最佳方法是什么?
更一般地说,我想找到一个模式的所有匹配项,然后使用由源字符串+新参数组成的新字符串更新每个模式,是否有人可以提出任何想法?
答案 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
}
(请注意,我稍微更改了您的正则表达式以分别匹配文件扩展名)
答案 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
}