为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
萧十郎 2021-11-15 15:56:27
我有一个日志文件,我需要使用 golang 解析其中的每条记录。每条记录以“#”开头,一条记录可以跨越一行或多行:# Line1# Line2Continued line2Continued 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            }    }谢谢,
查看完整描述

3 回答

?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

该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 上查看示例的完整实现。该文档将提供实现此类内容所需的所有见解。


查看完整回答
反对 回复 2021-11-15
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

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

    }

}


查看完整回答
反对 回复 2021-11-15
?
BIG阳

TA贡献1859条经验 获得超6个赞

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

    }

}


查看完整回答
反对 回复 2021-11-15
  • 3 回答
  • 0 关注
  • 180 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信