2 回答
TA贡献1817条经验 获得超14个赞
虽然使用 regexp 通常会产生一个优雅而紧凑的解决方案,但它通常不是最快的。
对于必须用其他子字符串替换某些子字符串的任务,标准库以以下形式提供了一个非常有效的解决方案strings.Replacer
:
Replacer 用替换项替换字符串列表。多个 goroutines 并发使用是安全的。
您可以使用创建可重复使用的替换器strings.NewReplacer()
,其中列出包含可替换部件及其替换件的对。当你想执行替换时,你只需调用Replacer.Replace()
.
它看起来像这样:
const replacement = "<br>\n"
var replacer = strings.NewReplacer(
"\r\n", replacement,
"\r", replacement,
"\n", replacement,
"\v", replacement,
"\f", replacement,
"\u0085", replacement,
"\u2028", replacement,
"\u2029", replacement,
)
func replaceReplacer(s string) string {
return replacer.Replace(s)
}
以下是Wiktor 答案中的正则表达式解决方案:
var re = regexp.MustCompile(`\r\n|[\r\n\v\f\x{0085}\x{2028}\x{2029}]`)
func replaceRegexp(s string) string {
return re.ReplaceAllString(s, "<br>\n")
}
实施实际上相当快。这是一个简单的基准测试,将其与上述预编译的正则表达式解决方案进行比较:
const input = "1st\nsecond\r\nthird\r4th\u0085fifth\u2028sixth"
func BenchmarkReplacer(b *testing.B) {
for i := 0; i < b.N; i++ {
replaceReplacer(input)
}
}
func BenchmarkRegexp(b *testing.B) {
for i := 0; i < b.N; i++ {
replaceRegexp(input)
}
}
基准测试结果:
BenchmarkReplacer-4 3000000 495 ns/op
BenchmarkRegexp-4 500000 2787 ns/op
对于我们的测试输入,速度提高了5 倍strings.Replacer
以上。
还有另一个优点。在上面的示例中,我们将结果作为新string
值获取(在两种解决方案中)。这需要一个新的string
分配。如果我们需要将结果写入一个io.Writer
(例如,我们正在创建一个 HTTP 响应或将结果写入一个文件),我们可以避免必须创建新的,string
因为strings.Replacer
它有一个方便的Replacer.WriteString()
方法,它接受一个io.Writer
并写入result into 它而不分配并将其作为 a 返回string
。与正则表达式解决方案相比,这进一步显着提高了性能增益。
TA贡献1866条经验 获得超5个赞
您可以将模式“解码”\R为
U+000DU+000A|[U+000AU+000BU+000CU+000DU+0085U+2028U+2029]
请参阅解释速记的Java 正则表达式文档\R:
Linebreak matcher
\R Any Unicode linebreak sequence, is equivalent to \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]
在 Go 中,您可以使用以下内容:
func removeLBR(text string) string {
re := regexp.MustCompile(`\x{000D}\x{000A}|[\x{000A}\x{000B}\x{000C}\x{000D}\x{0085}\x{2028}\x{2029}]`)
return re.ReplaceAllString(text, ``)
}
这是一个Go 演示。
一些 Unicode 代码可以用Go regexp支持的正则表达式转义序列替换:
re := regexp.MustCompile(`\r\n|[\r\n\v\f\x{0085}\x{2028}\x{2029}]`)
- 2 回答
- 0 关注
- 324 浏览
添加回答
举报