2 回答
TA贡献1890条经验 获得超9个赞
背景
完成任务的正确方法是匹配和捕获带引号的字符串(记住里面可以有转义的实体),然后匹配多行注释。
正则表达式代码演示
这是处理该问题的代码:
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"))
}
解释
我建议的 regex 是用Best Regex Trick Ever概念编写的,由 2 个替代方案组成:
("[^"\\]*(?:\\.[^"\\]*)*")-双引号字符串文字正则表达式- 第 1 组(参见由外部一对未转义括号形成的捕获组,稍后可通过替换反向引用访问)匹配可以包含转义序列的双引号字符串文字。这部分匹配:"- 领先的双引号[^"\\]*- 除了"and之外的 0+ 个字符\(因为[^...]构造是一个否定字符类,它匹配除其中定义的字符之外的任何字符)(the*是匹配量词的零次或多次出现)(?:\\.[^"\\]*)*"-转义序列的0+ 个序列(参见仅用于对子模式进行分组而不形成捕获的最后一个*和非捕获组)(匹配文字后跟任何字符)后跟 0+ 个字符而不是和\\.\"\|- 或者/\*[^*]*\*+(?:[^/*][^*]*\*+)*/-多行注释正则表达式部分匹配*而不形成捕获组(因此,无法通过反向引用从替换模式中获取)并匹配/-/字面斜线\*- 字面的星号[^*]*- 除星号外的零个或多个字符\*+- 1 个或多个(+是一个或多个匹配量词)星号(?:[^/*][^*]*\*+)*- 0+ 序列(非捕获,我们以后不会使用它)除了 a/或*(参见)之外的任何字符[^/*],后跟 0+ 星号以外的字符(参见[^*]*),然后是 1+ 星号(参见\*+)。/- 文字(尾随,结束)斜线。
注意:这个多行注释正则表达式是我测试过的最快的。双引号文字正则表达式"[^"\\]*(?:\\.[^"\\]*)*" 也是如此,因为它是用展开循环技术编写的:没有交替,只有以特定顺序使用*和+量词的字符类,以允许最快的匹配。
关于模式增强的说明
如果您计划扩展到匹配单引号文字,没有什么比这更容易的了,只需通过重新使用双引号字符串文字正则表达式并将双引号替换为单引号,将另一个替代方案添加到第一个捕获组中:
reg := regexp.MustCompile(`("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|/\*[^*]*\*+(?:[^/*][^*]*\*+)*/`)
^-------------------------^这是单引号和双引号文字支持正则表达式演示,删除了 miltiline 注释
添加单行注释支持类似:只需//[^\n\r]*在末尾添加替代项:
reg := regexp.MustCompile(`("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//.*[\r\n]*`)
^-----------^这是单引号和双引号文字支持正则表达式演示,删除了miltiline和单行注释
TA贡献1811条经验 获得超6个赞
这些不保留格式
首选方式(如果第 1 组不匹配,则产生 NULL)
在 golang 操场上有效 -
# https://play.golang.org/p/yKtPk5QCQV
# fmt.Println(reg.ReplaceAllString(txt, "$1"))
# (?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//[^\n]*(?:\n|$))|("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|[\S\s][^/"'\\]*)
(?: # Comments
/\* # Start /* .. */ comment
[^*]* \*+
(?: [^/*] [^*]* \*+ )*
/ # End /* .. */ comment
|
// [^\n]* # Start // comment
(?: \n | $ ) # End // comment
)
|
( # (1 start), Non - comments
"
[^"\\]* # Double quoted text
(?: \\ [\S\s] [^"\\]* )*
"
|
'
[^'\\]* # Single quoted text
(?: \\ [\S\s] [^'\\]* )*
'
| [\S\s] # Any other char
[^/"'\\]* # Chars which doesn't start a comment, string, escape, or line continuation (escape + newline)
) # (1 end)
替代方式(第 1 组始终匹配,但可能为空)
在 golang 游乐场中有效 -
# https://play.golang.org/p/7FDGZSmMtP
# fmt.Println(reg.ReplaceAllString(txt, "$1"))
# (?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//[^\n]*(?:\n|$))?((?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|[\S\s][^/"'\\]*)?)
(?: # Comments
/\* # Start /* .. */ comment
[^*]* \*+
(?: [^/*] [^*]* \*+ )*
/ # End /* .. */ comment
|
// [^\n]* # Start // comment
(?: \n | $ ) # End // comment
)?
( # (1 start), Non - comments
(?:
"
[^"\\]* # Double quoted text
(?: \\ [\S\s] [^"\\]* )*
"
|
'
[^'\\]* # Single quoted text
(?: \\ [\S\s] [^'\\]* )*
'
| [\S\s] # Any other char
[^/"'\\]* # Chars which doesn't start a comment, string, escape, or line continuation (escape + newline)
)?
) # (1 end)
Cadilac - 保留格式
(不幸的是,这不能在 Golang 中完成,因为 Golang 不能做断言)已
发布,以防您转移到不同的正则表达式引擎。
# raw: ((?:(?:^[ \t]*)?(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|/\*|//)))?|//(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|/\*|//))|(?=\r?\n))))+)|("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(?:\r?\n|[\S\s])[^/"'\\\s]*)
# delimited: /((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(?:\r?\n|[\S\s])[^\/"'\\\s]*)/
( # (1 start), Comments
(?:
(?: ^ [ \t]* )? # <- To preserve formatting
(?:
/\* # Start /* .. */ comment
[^*]* \*+
(?: [^/*] [^*]* \*+ )*
/ # End /* .. */ comment
(?: # <- To preserve formatting
[ \t]* \r? \n
(?=
[ \t]*
(?: \r? \n | /\* | // )
)
)?
|
// # Start // comment
(?: # Possible line-continuation
[^\\]
| \\
(?: \r? \n )?
)*?
(?: # End // comment
\r? \n
(?= # <- To preserve formatting
[ \t]*
(?: \r? \n | /\* | // )
)
| (?= \r? \n )
)
)
)+ # Grab multiple comment blocks if need be
) # (1 end)
| ## OR
( # (2 start), Non - comments
"
[^"\\]* # Double quoted text
(?: \\ [\S\s] [^"\\]* )*
"
|
'
[^'\\]* # Single quoted text
(?: \\ [\S\s] [^'\\]* )*
'
|
(?: \r? \n | [\S\s] ) # Linebreak or Any other char
[^/"'\\\s]* # Chars which doesn't start a comment, string, escape,
# or line continuation (escape + newline)
) # (2 end)
- 2 回答
- 0 关注
- 451 浏览
添加回答
举报
