regex - Golang 正则表达式替换不包括带引号的字符串

标签 regex go

我正在尝试在 Golang 中实现 removeComments 函数 this Javascript implementation .我希望从文本中删除任何评论。例如:

/* this is comments, and should be removed */

However, "/* this is quoted, so it should not be removed*/"

在 Javascript 实现中,引用匹配不会分组捕获,因此我可以轻松地将它们过滤掉。然而,在Golang中,似乎不太容易判断匹配的部分是否在一个组中被捕获。那么,如何在 Golang 中实现与 Javascript 版本中相同的 removeComments 逻辑呢?

最佳答案

背景

完成该任务的正确方法是匹配并捕获带引号的字符串(请记住内部可能存在转义实体),然后匹配多行注释。

正则表达式代码内演示

下面是处理这个问题的代码:

package main
import (
    "fmt"
    "regexp"
)
func main() {
    reg := regexp.MustCompile(`("[^"\\]*(?:\\.[^"\\]*)*")|/\*[^*]*\*+(?:[^/*][^*]*\*+)*/`)
        txt := `random text
            /* removable comment */
            "but /* never remove this */ one"
             more random *text*`
        fmt.Println(reg.ReplaceAllString(txt, "$1"))
}

参见 Playground demo

说明

我建议的正则表达式是用 Best Regex Trick Ever 编写的概念并由 2 个备选方案组成:

  • ("[^"\\]*(?:\\.[^"\\]*)*") - 双引号字符串文字正则表达式 -第 1 组(请参阅 capturing group 由外对未转义的括号组成,稍后可通过 replacement backreferences 访问)匹配可以包含转义序列的双引号字符串文字。这部分匹配:
    • " - 前导双引号
    • [^"\\]* - "\ 以外的 0+ 个字符(如 [^... ] 构造是一个 negated character class 匹配除其中定义的字符之外的任何字符)(* 是匹配 quantifier0 次或多次 )
    • (?:\\.[^"\\]*)*" - 0+ 序列(参见最后的 *non-capturing group 仅用于group 子模式而不形成捕获)转义序列(\\. 匹配文字 \ 后跟任何字符)后跟 0+ "\
    • 以外的字符
  • | - 或者
  • /\*[^*]*\*+(?:[^/*][^*]*\*+)*/ - 多行注释正则表达式 部分匹配 * 没有形成捕获组(因此,无法通过反向引用从替换模式中获取)和匹配
    • / - / 斜线
    • \* - 星号
    • [^*]* - 星号以外的零个或多个字符
    • \*+ - 1 个或多个(+ 是一个一个或多个匹配量词)星号
    • (?:[^/*][^*]*\*+)* - 除了 /*(参见 [^/*]),后跟除星号以外的 0+ 个字符(参见 [^*] *),然后是 1+ 个星号(参见 \*+)。
    • / - 文字(尾随、结束)斜线。

注意:这个多行注释正则表达式是我测试过的最快的。同样适用于双引号文字正则表达式,如 "[^"\\]*(?:\\.[^"\\]*)*" 是用 unroll-the-loop technique 写的请记住:没有交替,仅以特定顺序使用带有 *+ 量词的字符类,以实现最快的匹配。

模式增强注意事项

如果您打算扩展到匹配单引号文字,没有什么比这更容易的了,只需通过重新使用双引号字符串文字正则表达式并将双引号替换为单引号,将另一个替代方法添加到第一个捕获组中:

reg := regexp.MustCompile(`("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|/\*[^*]*\*+(?:[^/*][^*]*\*+)*/`)
                                                    ^-------------------------^

这是 single- and double-quoted literal supporting regex demo removing the miltiline comments

添加单行注释支持类似:只需在末尾添加 //[^\n\r]* 替代:

reg := regexp.MustCompile(`("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//.*[\r\n]*`)
                                                                                                              ^-----------^

这里是 single- and double-quoted literal supporting regex demo removing the miltiline and singleline comments

关于regex - Golang 正则表达式替换不包括带引号的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36725194/

相关文章:

regex - CMake正则表达式匹配列表中的目录

php - 正则表达式 : Converting non-block elements with <br/> to <p> in PHP

go - 使用 Golang 与 hiveserver2 通信

go - 如何通过 http ://in Go? 发出仅限 HTTP2 的请求

javascript - jquery 封装电子邮件地址

正则表达式等价

go - 为什么关闭sftp客户端不会关闭整个SSH连接

go - 注销后如何停止 session 缓存经过身份验证的用户数据

python - 使用正则表达式以逗号分隔南亚编号系统中的大量数字

amazon-web-services - aws xray 和 golang http 调用