【问题标题】:How to replace optional group with regex and Golang如何用正则表达式和 Golang 替换可选组
【发布时间】:2017-04-03 08:54:17
【问题描述】:

我正在尝试翻译这个:

{% img <right> /images/testing %}

进入这个:

{{< figure <class="right"> src="/images/testing" >}}

在 Golang 中使用正则表达式。源字符串中&lt;&gt; 中的部分是可选的。

当第一个捕获组存在时(“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=") 消失吗?

【问题讨论】:

标签: regex go


【解决方案1】:

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,用函数值的输出替换每次出现的模式。然后,此函数可以决定是否包含特定格式。

【讨论】:

    猜你喜欢
    • 2021-07-29
    • 2017-09-21
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多