我正在尝试编写一个函数来截断golang中带有特殊字符的字符串。一个例子如下:
"H㐀〾▓朗퐭텟şüöžåйкл¤"
但是我根据允许的字符数量在中间切割它。这会导致数据损坏。
结果如
H㐀〾▓朗퐭텟şüöžå�...
�
不应该在那里。我们如何检测这些特殊字符并根据这些字符的长度进行拆分?
package main
import (
"fmt"
"regexp"
)
var reNameBlacklist = regexp.MustCompile(`(&|>|<|\/|:|\n|\r)*`)
var maxFileNameLength = 30
// SanitizeName sanitizes user names in an email
func SanitizeName(name string, limit int) string {
result := name
reNameBlacklist.ReplaceAllString(result, "")
if len(result) > limit {
result = result[:limit] + "..."
}
return result
}
func main() {
str := "H㐀〾▓朗퐭텟şüöžåйкл¤"
fmt.Println(str)
strsan := SanitizeName(str, maxFileNameLength)
fmt.Println(strsan)
}
答案 0 :(得分:8)
切片字符串将它们视为基础字节数组; slice运算符对字节索引进行操作,而不是符文(每个符号可以是多个字节)。但是,range
超过一个字符串迭代符文 - 但返回的索引是字节。这样可以非常直接地完成您正在寻找的内容(full playground example here):
func SanitizeName(name string, limit int) string {
reNameBlacklist.ReplaceAllString(name, "")
result := name
chars := 0
for i := range name {
if chars >= limit {
result = name[:i]
break
}
chars++
}
return result
}
更详细地解释了这一点on the Go blog
答案 1 :(得分:2)
您的数据损坏的原因是因为某些字符使用多个字节并且您正在拆分它们。为了避免这种情况,Go的类型rune
表示UTF-8字符。您可以将字符串转换为[]rune
,如下所示:
func SanitizeName(name string, limit int) string{
reNameBlacklist.ReplaceAllString(name, "")
result := []rune(name)
// Remove the special chars here
return string(result[:limit])
}
这应该只保留第一个限制 UTF-8字符。
答案 2 :(得分:0)
另一个选项是 utf8string
包:
package main
import "golang.org/x/exp/utf8string"
func main() {
s := utf8string.NewString("?????")
t := s.Slice(0, 2)
println(t == "??")
}