猿问

如何使用自定义拆分实现扫描仪

我有一个日志文件,我需要使用 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

            }

    }

谢谢,


萧十郎
浏览 181回答 3
3回答

哆啦的时光机

该Scanner类型有一个名为Split的函数,它允许您传递 aSplitFunc来确定扫描器将如何拆分给定的字节片。默认SplitFunc是ScanLines你可以看到的实现源。从这一点上,您可以根据您的特定格式编写自己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 上查看示例的完整实现。该文档将提供实现此类内容所需的所有见解。

慕桂英546537

Ben Campbell和sto-b-doo 的稍微优化的解决方案字节切片到字符串的转换似乎是一个相当繁重的操作。在我的日志处理应用程序中,它成为了瓶颈。仅以字节为单位保留数据可为我的应用程序提供约 1500% 的性能提升。func SplitAt(substring string) func(data []byte, atEOF bool) (advance int, token []byte, err error) {    searchBytes := []byte(substring)    searchLen := len(searchBytes)    return func(data []byte, atEOF bool) (advance int, token []byte, err error) {        dataLen := len(data)        // Return nothing if at end of file and no data passed        if atEOF && dataLen == 0 {            return 0, nil, nil        }        // Find next separator and return token        if i := bytes.Index(data, searchBytes); i >= 0 {            return i + searchLen, data[0:i], nil        }        // If we're at EOF, we have a final, non-terminated line. Return it.        if atEOF {            return dataLen, data, nil        }        // Request more data.        return 0, nil, nil    }}

BIG阳

Ben Campbell 的答案包含在一个函数中,该函数返回子字符串的 splitfunc:play.golang.org 上的演示欢迎改进建议// 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    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答