从字符串中删除空字符
remove null character from string
我想检查字符串是否为空并及时解析字符串。
请找到下面的代码
valueStr = strings.Replace(string(valueStr), " ", "", -1)
valueStr = strings.Replace(string(valueStr), "\t", "", -1)
valueStr = strings.Replace(string(valueStr), "\n", "", -1)
valueStr = strings.Replace(string(valueStr), "\r", "", -1)
var re = regexp.MustCompile(`\s`)
valueStr = re.ReplaceAllString(valueStr, "")
if valueStr != "" {
fmt.Printf("-------- valueStr %c: \n", valueStr) // o/p => -------- valueStr %!c(string= ):
fmt.Printf("-------- valueStr %#v: \n", valueStr) // o/p => -------- valueStr "\x00":
fmt.Printf("-------- valueStr %x: \n", valueStr) // o/p => -------- valueStr 00:
fmt.Println("-------- valueStr length: ", len(valueStr)) // o/p => -------- valueStr length: 1
// considering valueStr is not empty, parse string to time
time, err := time.Parse(TIME_FORMAT, strings.TrimSpace(valueStr))
if err != nil {
fmt.Println("-------- Error converting time: ", err) // o/p => -------- Error converting time: parsing time " " as "15:04:05": cannot parse " " as "15"
return
}
} else {
// another code
}
如何从字符串中删除这个空字符?或者检查字符串是否包含这个空字符?
您可以从字符串中删除 \x00
运行es,就像删除任何其他 运行es:
一样
valueStr = strings.Replace(valueStr, "\x00", "", -1)
示例:
s := "a\x00b"
fmt.Printf("%q\n", s)
s = strings.Replace(s, "\x00", "", -1)
fmt.Printf("%q\n", s)
输出(在 Go Playground 上尝试):
"a\x00b"
"ab"
使用strings.Replacer
另请注意,您可以使用 strings.Replacer
将多个替换替换为单个操作,并且它也会更有效,因为它只迭代输入一次(并且只有一个 string
分配给结果,不管你要替换多少个子串)。
例如:
s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)
r := strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
s = r.Replace(s)
fmt.Printf("%q\n", s)
输出(在 Go Playground 上尝试):
" \t\n\rabc\x00"
"abc"
另请注意,创建一个 string.Replacer
一次就足够了,您可以将它存储在一个(全局)变量中并重用它,从多个 goroutine 中同时使用它甚至是安全的。
使用strings.Map()
另请注意,如果您只想替换(删除)单个 rune
而不是 multi-rune(或 multi-byte)子字符串,您也可以使用 strings.Map()
这可能比 strings.Replacer
.
更有效
首先定义一个函数,告诉要替换哪些 rune
(如果 return 是负值,则删除):
func remove(r rune) rune {
switch r {
case ' ', '\t', '\n', '\r', 0:
return -1
}
return r
}
然后使用它:
s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)
s = strings.Map(remove, s)
fmt.Printf("%q\n", s)
输出(在 Go Playground 上尝试):
" \t\n\rabc\x00"
"abc"
基准
我们可能会认为 strings.Map()
会更优越,因为它只需要处理 rune
就只是 int32
个数字,而 strings.Replacer
必须处理 string
值是 headers(长度+数据指针)加上一系列字节。
但是我们应该知道 string
值在内存中存储为 UTF-8 字节序列,这意味着 strings.Map()
必须从 UTF-8 字节解码 rune
s序列(并最终将 运行es 编码回 UTF-8),而 strings.Replacer
不会:它可能只是查找字节序列匹配而不解码 rune
s。 strings.Replacer
被高度优化以利用 "tricks".
所以让我们创建一个基准来比较它们:
我们将使用这些作为基准:
var r = strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
func remove(r rune) rune {
switch r {
case ' ', '\t', '\n', '\r', 0:
return -1
}
return r
}
我们 运行 对不同的输入字符串进行基准测试:
func BenchmarkReplaces(b *testing.B) {
cases := []struct {
title string
input string
}{
{
title: "None",
input: "abc",
},
{
title: "Normal",
input: " \t\n\rabc\x00",
},
{
title: "Long",
input: "adsfWR \t\rab\nc\x00 \t\n\rabc\x00asdfWER\n\r",
},
}
for _, c := range cases {
b.Run("Replacer-"+c.title, func(b *testing.B) {
for i := 0; i < b.N; i++ {
r.Replace(c.input)
}
})
b.Run("Map-"+c.title, func(b *testing.B) {
for i := 0; i < b.N; i++ {
strings.Map(remove, c.input)
}
})
}
}
现在让我们看看基准测试结果:
BenchmarkReplaces/Replacer-None-4 100000000 12.3 ns/op 0 B/op 0 allocs/op
BenchmarkReplaces/Map-None-4 100000000 16.1 ns/op 0 B/op 0 allocs/op
BenchmarkReplaces/Replacer-Normal-4 20000000 92.7 ns/op 6 B/op 2 allocs/op
BenchmarkReplaces/Map-Normal-4 20000000 92.4 ns/op 16 B/op 2 allocs/op
BenchmarkReplaces/Replacer-Long-4 5000000 234 ns/op 64 B/op 2 allocs/op
BenchmarkReplaces/Map-Long-4 5000000 235 ns/op 80 B/op 2 allocs/op
尽管有预期,string.Replacer
表现相当不错,与 strings.Map()
一样好,因为它不需要解码和编码 运行es。
我不知道这是否是您的情况,但就我而言,我收到了来自 Windows 系统调用的 uint16
切片。在这种情况下,数据也由 null 元素终止。要解决这个问题,您可以使用 windows
包:
package main
import (
"fmt"
"golang.org/x/sys/windows"
)
func main() {
a := []uint16{77, 97, 114, 99, 104, 0}
s := windows.UTF16ToString(a)
fmt.Printf("%q\n", s) // "March"
}
在当前 Python(截至 2021 年 11 月)和 Windows 10 下,这段代码对我有用:
s = str.replace(s, "\x00", "", -1)
我想检查字符串是否为空并及时解析字符串。
请找到下面的代码
valueStr = strings.Replace(string(valueStr), " ", "", -1)
valueStr = strings.Replace(string(valueStr), "\t", "", -1)
valueStr = strings.Replace(string(valueStr), "\n", "", -1)
valueStr = strings.Replace(string(valueStr), "\r", "", -1)
var re = regexp.MustCompile(`\s`)
valueStr = re.ReplaceAllString(valueStr, "")
if valueStr != "" {
fmt.Printf("-------- valueStr %c: \n", valueStr) // o/p => -------- valueStr %!c(string= ):
fmt.Printf("-------- valueStr %#v: \n", valueStr) // o/p => -------- valueStr "\x00":
fmt.Printf("-------- valueStr %x: \n", valueStr) // o/p => -------- valueStr 00:
fmt.Println("-------- valueStr length: ", len(valueStr)) // o/p => -------- valueStr length: 1
// considering valueStr is not empty, parse string to time
time, err := time.Parse(TIME_FORMAT, strings.TrimSpace(valueStr))
if err != nil {
fmt.Println("-------- Error converting time: ", err) // o/p => -------- Error converting time: parsing time " " as "15:04:05": cannot parse " " as "15"
return
}
} else {
// another code
}
如何从字符串中删除这个空字符?或者检查字符串是否包含这个空字符?
您可以从字符串中删除 \x00
运行es,就像删除任何其他 运行es:
valueStr = strings.Replace(valueStr, "\x00", "", -1)
示例:
s := "a\x00b"
fmt.Printf("%q\n", s)
s = strings.Replace(s, "\x00", "", -1)
fmt.Printf("%q\n", s)
输出(在 Go Playground 上尝试):
"a\x00b"
"ab"
使用strings.Replacer
另请注意,您可以使用 strings.Replacer
将多个替换替换为单个操作,并且它也会更有效,因为它只迭代输入一次(并且只有一个 string
分配给结果,不管你要替换多少个子串)。
例如:
s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)
r := strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
s = r.Replace(s)
fmt.Printf("%q\n", s)
输出(在 Go Playground 上尝试):
" \t\n\rabc\x00"
"abc"
另请注意,创建一个 string.Replacer
一次就足够了,您可以将它存储在一个(全局)变量中并重用它,从多个 goroutine 中同时使用它甚至是安全的。
使用strings.Map()
另请注意,如果您只想替换(删除)单个 rune
而不是 multi-rune(或 multi-byte)子字符串,您也可以使用 strings.Map()
这可能比 strings.Replacer
.
首先定义一个函数,告诉要替换哪些 rune
(如果 return 是负值,则删除):
func remove(r rune) rune {
switch r {
case ' ', '\t', '\n', '\r', 0:
return -1
}
return r
}
然后使用它:
s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)
s = strings.Map(remove, s)
fmt.Printf("%q\n", s)
输出(在 Go Playground 上尝试):
" \t\n\rabc\x00"
"abc"
基准
我们可能会认为 strings.Map()
会更优越,因为它只需要处理 rune
就只是 int32
个数字,而 strings.Replacer
必须处理 string
值是 headers(长度+数据指针)加上一系列字节。
但是我们应该知道 string
值在内存中存储为 UTF-8 字节序列,这意味着 strings.Map()
必须从 UTF-8 字节解码 rune
s序列(并最终将 运行es 编码回 UTF-8),而 strings.Replacer
不会:它可能只是查找字节序列匹配而不解码 rune
s。 strings.Replacer
被高度优化以利用 "tricks".
所以让我们创建一个基准来比较它们:
我们将使用这些作为基准:
var r = strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
func remove(r rune) rune {
switch r {
case ' ', '\t', '\n', '\r', 0:
return -1
}
return r
}
我们 运行 对不同的输入字符串进行基准测试:
func BenchmarkReplaces(b *testing.B) {
cases := []struct {
title string
input string
}{
{
title: "None",
input: "abc",
},
{
title: "Normal",
input: " \t\n\rabc\x00",
},
{
title: "Long",
input: "adsfWR \t\rab\nc\x00 \t\n\rabc\x00asdfWER\n\r",
},
}
for _, c := range cases {
b.Run("Replacer-"+c.title, func(b *testing.B) {
for i := 0; i < b.N; i++ {
r.Replace(c.input)
}
})
b.Run("Map-"+c.title, func(b *testing.B) {
for i := 0; i < b.N; i++ {
strings.Map(remove, c.input)
}
})
}
}
现在让我们看看基准测试结果:
BenchmarkReplaces/Replacer-None-4 100000000 12.3 ns/op 0 B/op 0 allocs/op
BenchmarkReplaces/Map-None-4 100000000 16.1 ns/op 0 B/op 0 allocs/op
BenchmarkReplaces/Replacer-Normal-4 20000000 92.7 ns/op 6 B/op 2 allocs/op
BenchmarkReplaces/Map-Normal-4 20000000 92.4 ns/op 16 B/op 2 allocs/op
BenchmarkReplaces/Replacer-Long-4 5000000 234 ns/op 64 B/op 2 allocs/op
BenchmarkReplaces/Map-Long-4 5000000 235 ns/op 80 B/op 2 allocs/op
尽管有预期,string.Replacer
表现相当不错,与 strings.Map()
一样好,因为它不需要解码和编码 运行es。
我不知道这是否是您的情况,但就我而言,我收到了来自 Windows 系统调用的 uint16
切片。在这种情况下,数据也由 null 元素终止。要解决这个问题,您可以使用 windows
包:
package main
import (
"fmt"
"golang.org/x/sys/windows"
)
func main() {
a := []uint16{77, 97, 114, 99, 104, 0}
s := windows.UTF16ToString(a)
fmt.Printf("%q\n", s) // "March"
}
在当前 Python(截至 2021 年 11 月)和 Windows 10 下,这段代码对我有用:
s = str.replace(s, "\x00", "", -1)