我正在尝试翻译这个:
{% img <right> /images/testing %}
进入这个:
{{< figure <class="right"> src="/images/testing" >}}
在 Golang 中使用正则表达式。 <>
中的部分在源字符串中是可选的。
我有这段代码,当第一个捕获组存在时(“right”),它似乎在主测试用例中工作:
regexp.MustCompile(`{%\s*img\s*(\p{L}*)\s+([/\S]+)\s+%}`)
.ReplaceAllString("{% img right /images/testing %}", "{{< figure class=\"$1\" src=\"$2\" >}}")
但是,如果缺少可选组,我会得到:
{{< figure class="" src="/images/testing" >}}
这不是我需要的 - 我想要整个 class=""
部分不见了,像这样:
{{< figure src="/images/testing" >}}
这可能吗?我可以在替换字符串中以某种方式指出吗:
{{< figure class=\"$1\" src=\"$2\" >}}
如果可选组为空,我希望附加文本(“class=”)消失?
最佳答案
Go 正则表达式不支持条件语句,正则表达式函数的 Replace
系列也不支持。
对此的解决方案取决于您拥有的特殊情况的数量。
如果您只有一种情况,我建议只进行两次替换:首先用属性集替换所有出现的情况,然后替换所有没有属性的情况 (on play):
txt := `{% img right /images/testing %}\n{% img /images/testing %}`
// without attribute
txt = regexp.MustCompile(`{%\s*img\s*([/\S]+)\s+%}`).
ReplaceAllString(txt, "{{< figure src=\"$1\" >}}")
// with attribute
txt = regexp.MustCompile(`{%\s*img\s*(\p{L}*)\s+([/\S]+)\s+%}`).
ReplaceAllString(txt, "{{< figure class=\"$1\" src=\"$2\" >}}")
如果您说这效率低下,我会说:可能是的。如果你想要更高效的东西(即不重复源字符串两次的东西),那么你必须构建更类似于解析器的东西,它在检测时决定使用哪种格式。粗略的描述如下(on play):
src := []byte("ok" + "{% img right /images/testing %}" + "this" +
"{% img /images/testing %}" + "no?")
dst := bytes.NewBufferString("")
cidx := 0
for _, match := range p.FindAllSubmatchIndex(src, -1) {
dst.Write(src[cidx:match[0]])
dst.WriteString(newFormat(src, src[match[2]:match[3]], src[match[4]:match[5]]))
cidx = match[1]
}
dst.Write(src[cidx:])
在此示例中,您将源文本 src
中的所有内容复制到缓冲区 dst
中,用函数值的输出替换您的模式的每次出现。然后,此函数可以决定是否包含特定格式。
关于regex - 如何用正则表达式和 Golang 替换可选组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43168329/