【发布时间】:2020-06-12 20:18:59
【问题描述】:
我正在使用string.Replace 替换子字符串A
func removeIP(text string) string {
text = strings.Replace(text, "someWord", "**NewWord**", -1)
return text
}
func removeIPUsingRegex(text string) string {
var re = regexp.MustCompile(`\b` + "someWord" + `\b`) // I want to replace whole word only
text = re.ReplaceAllString(text, "**NewWord**")
}
我在这里面临的问题是,我只想在字符串替换不支持的情况下替换整个单词。
因为我必须替换非常非常大的字符串,所以可能以 GB 为单位。与字符串替换相比,正则表达式非常慢。
例如:文本:"abcdef defgh /def/ .def/ =def= def xxxy" -> 将 def 替换为 DEF
output: "abcdef defgh /DEF/ .DEF/ =DEF= DEF xxxy" //注意只有整个单词被替换了。
Regex 将时间缩短了近 100 倍 (https://medium.com/codezillas/golang-replace-vs-regexp-de4e48482f53)。任何想法将不胜感激。
【问题讨论】:
-
正则表达式需要更长时间的原因是它更复杂,这也是它实际工作的原因。简单的字符串替换过于简单,无法处理您正在干燥的事情。您可以编写自己的替换函数,逐个字符地迭代字符串,其性能可能介于
strings.Replace和regexp.ReplaceAllString之间,但也需要在开发和测试方面付出更多努力。 -
如果您的文本有几 GB 大,并且您使用
io.Reader访问它,您也可以 look at this question 关于在流式传输时替换字符,但是它不能回答“整个单词”的问题 -
您可以使用非常快速的字符串搜索和 Index() 来查找子字符串匹配的位置。然后检查匹配前后的字符。如果它们不是字母,则替换出现的子字符串。这将比替换稍慢。
-
对我之前评论的补充:要查找从字符串内某个索引开始的子字符串的位置,请使用 Slice() 然后 Index():stackoverflow.com/questions/54090467/…
-
是的,流式阅读是最有可能的答案。 Go 的 re2 已经是最高效的正则表达式引擎之一,但仍然不适合(真正的)大文件。