我正在尝试在 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"))
}
说明
我建议的正则表达式是用 Best Regex Trick Ever 编写的概念并由 2 个备选方案组成:
("[^"\\]*(?:\\.[^"\\]*)*")
- 双引号字符串文字正则表达式 -第 1 组(请参阅 capturing group 由外对未转义的括号组成,稍后可通过 replacement backreferences 访问)匹配可以包含转义序列的双引号字符串文字。这部分匹配:"
- 前导双引号[^"\\]*
-"
和\
以外的 0+ 个字符(如[^... ]
构造是一个 negated character class 匹配除其中定义的字符之外的任何字符)(*
是匹配 quantifier 的 0 次或多次 )(?:\\.[^"\\]*)*"
- 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]*`)
^-----------^
关于regex - Golang 正则表达式替换不包括带引号的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36725194/