gpt4 book ai didi

parsing - 从字符串中的子字符串中解析日期

转载 作者:IT王子 更新时间:2023-10-29 01:40:04 29 4
gpt4 key购买 nike

我正在编写一个日志文件解析器,并编写了一些测试代码来用 C 语言解析它。

要解析的字符串如下所示:

s := `10.0.0.1 Jan 11 2014 10:00:00 hello`

在 C 中,就地解析它非常容易。首先,我在字符串中找到指向日期的指针,然后使用 strptime() 尽可能多地使用。这是可能的,因为 strptime() 将在调用后返回字符串中的位置。

最终我决定使用 Go 而不是 C,但是在移植代码时我遇到了一些问题。据我所知, time.Parse() 没有给我任何从现有字符串中解析的选项(尽管这可以用 slice 解决)或指示在解析日期时它消耗了多少原始字符串从字符串中。

在 Go 中有什么优雅的方法可以直接从字符串中解析日期/时间,而不必首先将日期时间提取到一个精确的 slice 中,例如通过返回解析后提取的字符数?

最佳答案

不幸的是,time.Parse 方法无法告诉您它解析了多少个字符,因此我们需要研究其他优雅的解决方案。在您解析日志语句的示例中,正如@rob74 建议的那样,使用正则表达式是一种相当优雅的策略。为简洁起见,下面的示例忽略了错误:

var r = regexp.MustCompile(`^((?:\d{1,3}\.){3}\d{1,3}) ([a-zA-Z]{3} \d{1,2} \d{4} \d{1,2}:\d{2}:\d{2}) (.*)`)
const longForm = "Jan 02 2006 15:04:05"

func parseRegex(s string) (ip, msg string, t time.Time) {
m := r.FindStringSubmatch(s)
t, _ = time.Parse(longForm, m[2])
ip, msg = m[1], m[3]
return ip, msg, t
}

基准测试显示上述正则表达式在我的机器上比 @rob74 的示例效率高两倍,每秒解析大约 100,000 行:

BenchmarkParseRegex           100000         17130 ns/op
BenchmarkParseRegexRob74 50000 32788 ns/op

但是,如果我们改用 strings.SplitN,我们可以使解决方案更简短、更高效。例如:

func parseSplit(s string) (ip, msg string, t time.Time) {
parts := strings.SplitN(s, " ", 6)
t, _ = time.Parse(longForm, strings.Join(parts[1:5], " "))
ip, msg = parts[0], parts[5]
return ip, msg, t
}

这会在前 5 个空格上拆分字符串,并将剩余的字符串(消息部分)放入最后的 parts slice 元素中。这不是很优雅,因为我们依赖于日期格式中的空格数,但我们可以通过编程方式计算日期格式字符串中的空格以获得更通用的解决方案。让我们看看这与我们的正则表达式解决方案相比如何:

BenchmarkParseRegex   100000         17130 ns/op
BenchmarkParseSplit 500000 3557 ns/op

事实证明,它比较有利。使用 SplitN 比使用正则表达式快大约五倍,而且代码仍然简洁易读。这样做的代价是为 slice 分配使用更多的内存。

关于parsing - 从字符串中的子字符串中解析日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21830563/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com