我有一个日志文件,我需要使用golang解析其中的每条记录。 每条记录都以"#"开头,一条记录可以跨越一行或多行:
# Line1
# Line2
Continued line2
Continued line2
# line3
.....
一些代码:),我是初学者
f, _ := os.Open(mylog)
scanner := bufio.NewScanner(f)
var queryRec string
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "# ") && len(queryRec) == 0 {
queryRec = line
} else if !strings.HasPrefix(line, "# ") && len(queryRec) == 0 {
fmt.Println("There is a big problem!!!")
} else if !strings.HasPrefix(line, "# ") && len(queryRec) != 0 {
queryRec += line
} else if strings.HasPrefix(line, "# ") && len(queryRec) != 0 {
queryRec = line
}
}
谢谢,
答案 0 :(得分:10)
Scanner
类型有一个名为Split的函数,它允许您传递SplitFunc
以确定扫描程序如何拆分给定的字节切片。默认SplitFunc
是ScanLines
,您可以看到implementation source。从这一点开始,您可以根据自己的特定格式编写自己的SplitFunc
来打破bufio.Reader
内容。
func crunchSplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
// Return nothing if at end of file and no data passed
if atEOF && len(data) == 0 {
return 0, nil, nil
}
// Find the index of the input of a newline followed by a
// pound sign.
if i := strings.Index(string(data), "\n#"); i >= 0 {
return i + 1, data[0:i], nil
}
// If at end of file with data return the data
if atEOF {
return len(data), data, nil
}
return
}
您可以在https://play.golang.org/p/ecCYkTzme4看到示例的完整实现。该文档将提供实现此类内容所需的所有见解。
答案 1 :(得分:1)
Ben Campbell和sto-b-doo的稍微优化的解决方案
将字节片转换为字符串似乎是很繁重的操作。
在我用于日志处理的应用程序中,它成为了瓶颈。
仅以字节为单位的数据就可以为我的应用程序带来〜1500%的性能提升。
Double
答案 2 :(得分:0)
Ben Campbell's answer包裹在一个函数中,该函数返回用于子字符串的splitfunc:
欢迎提出改进建议
// SplitAt returns a bufio.SplitFunc closure, splitting at a substring
// scanner.Split(SplitAt("\n# "))
func SplitAt(substring string) func(data []byte, atEOF bool) (advance int, token []byte, err error) {
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
// Return nothing if at end of file and no data passed
if atEOF && len(data) == 0 {
return 0, nil, nil
}
// Find the index of the input of the separator substring
if i := strings.Index(string(data), substring); i >= 0 {
return i + len(substring), data[0:i], nil
}
// If at end of file with data return the data
if atEOF {
return len(data), data, nil
}
return
}
}
答案 3 :(得分:0)
希望比 stu0292's improvements 有所改进(可能是可读性) 并使用最终令牌信号。
// SplitAt returns a bufio.SplitFunc closure, splitting at a substring
// scanner.Split(SplitAt("\n#"))
func SplitAt(substring string) func(data []byte, atEOF bool) (advance int, token []byte, err error) {
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
// Find the index of the input of the separator substring
if i := strings.Index(string(data), substring); i >= 0 {
return i + len(substring), data[0:i], nil
}
if !atEOF {
return 0, nil, nil
}
return len(data), data, bufio.ErrFinalToken
}
}