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

GO中日志文件的文本解析

GO中日志文件的文本解析

Go
慕标琳琳 2023-07-26 17:19:39
新手来这里吧!我正在尝试编写一个 Go 程序,该程序将解析日志文件并返回匹配行的特定信息。为了举例说明我想要实现的目标,我将从一个如下所示的日志文件开始:2019-09-30T04:17:02 - REQUEST-A2019-09-30T04:18:02 - REQUEST-C2019-09-30T04:19:02 - REQUEST-B2019-09-30T04:20:02 - REQUEST-A2019-09-30T04:21:02 - REQUEST-A2019-09-30T04:22:02 - REQUEST-B从这里我想提取所有“REQUEST-A”并将请求发生的时间打印到终端或文件。我尝试过使用 os.Open 和 Scanner,并且可以使用 Scanner.Text 来记录它已发现我的字符串的出现,如下所示:package mainimport (    "bufio"    "fmt"    "os"    "strings")func main() {    request := 0    f, err := os.Open("request.log")    if err != nil {        fmt.Print("There has been an error!: ", err)    }    defer f.Close()    scanner := bufio.NewScanner(f)    for scanner.Scan() {        if strings.Contains(scanner.Text(), "REQUEST-A") {            request = request + 1        }        if err := scanner.Err(); err != nil {        }        fmt.Println(request)    }}但我不确定如何用它来检索我想要的信息。通常我会使用 Bash,但我想我应该扩展一下,看看是否可以使用 Go。任何建议将不胜感激。
查看完整描述

3 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

在 Go 中,我们努力提高效率。不要做不必要的事情。


例如,


package main


import (

    "bufio"

    "bytes"

    "fmt"

    "os"

)


func main() {

    lines, requestA := 0, 0

    f, err := os.Open("request.log")

    if err != nil {

        fmt.Print("There has been an error!: ", err)

    }

    defer f.Close()


    scanner := bufio.NewScanner(f)

    for scanner.Scan() {

        lines++

        // filter request a

        line := scanner.Bytes()

        if len(line) <= 30 || line[30] != 'A' {

            continue

        }

        if !bytes.Equal(line[22:], []byte("REQUEST-A")) {

            continue

        }

        requestA++

        request := string(line)


        // handle request a

        fmt.Println(request)

    }

    if err := scanner.Err(); err != nil {

        fmt.Println(err)

    }

    fmt.Println(lines, requestA)

}

输出:


$ go run request.go


2019-09-30T04:17:02 - REQUEST-A

2019-09-30T04:20:02 - REQUEST-A

2019-09-30T04:21:02 - REQUEST-A

6 3


$ cat request.log

2019-09-30T04:17:02 - REQUEST-A

2019-09-30T04:18:02 - REQUEST-C

2019-09-30T04:19:02 - REQUEST-B

2019-09-30T04:20:02 - REQUEST-A

2019-09-30T04:21:02 - REQUEST-A

2019-09-30T04:22:02 - REQUEST-B

为了强调效率的重要性(日志可能非常大),让我们针对Markus W Mahlberg的解决方案运行一个基准测试:https://play.golang.org/p/R2D_BeiJvx9。


$ go test log_test.go -bench=. -benchmem

BenchmarkPeterSO-4   21285     56953 ns/op    4128 B/op      2 allocs/op

BenchmarkMarkusM-4     649   1817868 ns/op   84747 B/op   2390 allocs/op

log_test.go:


package main


import (

    "bufio"

    "bytes"

    "regexp"

    "strings"

    "testing"

)


var requestLog = `

2019-09-30T04:17:02 - REQUEST-A

2019-09-30T04:18:02 - REQUEST-C

2019-09-30T04:19:02 - REQUEST-B

2019-09-30T04:20:02 - REQUEST-A

2019-09-30T04:21:02 - REQUEST-A

2019-09-30T04:22:02 - REQUEST-B

`


var benchLog = strings.Repeat(requestLog[1:], 256)


func BenchmarkPeterSO(b *testing.B) {

    for N := 0; N < b.N; N++ {

        scanner := bufio.NewScanner(strings.NewReader(benchLog))

        for scanner.Scan() {

            // filter request a

            line := scanner.Bytes()

            if len(line) <= 30 || line[30] != 'A' {

                continue

            }

            if !bytes.Equal(line[22:], []byte("REQUEST-A")) {

                continue

            }

            request := string(line)

            // handle request a

            _ = request

        }

        if err := scanner.Err(); err != nil {

            b.Fatal(err)

        }

    }

}


func BenchmarkMarkusM(b *testing.B) {

    for N := 0; N < b.N; N++ {

        var re *regexp.Regexp = regexp.MustCompile(`^(\S*) - REQUEST-A$`)

        scanner := bufio.NewScanner(strings.NewReader(benchLog))

        var res []string

        for scanner.Scan() {

            if res = re.FindStringSubmatch(scanner.Text()); len(res) > 0 {

                _ = res[1]

            }

        }

        if err := scanner.Err(); err != nil {

            b.Fatal(err)

        }

    }

}



查看完整回答
反对 回复 2023-07-26
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

使用以下代码打印值为“REQUEST-A”的日志条目的时间字段。


for scanner.Scan() {

    line := scanner.Text()

    if len(line) < 19 {

        continue

    }

    if line[19:] == " - REQUEST-A" {

        fmt.Println(line[:19])

    }

}

在围棋游乐场上运行它!

要写入文件,请将 stdout 重定向到文件。


上面的代码假设时间戳之后的所有内容都是“-REQUEST-A”。如果“-REQUEST-A”是其他数据的前缀,请使用以下内容:


const lenTimestamp = 19

for scanner.Scan() {

    line := scanner.Text()

    if len(line) < lenTimestamp {

        continue

    }

    if strings.HasPrefix(line[lenTimestamp:], " - REQUEST-A") {

        fmt.Println(line[:lenTimestamp])

    }

}

在操场上运行这个版本



查看完整回答
反对 回复 2023-07-26
?
函数式编程

TA贡献1807条经验 获得超9个赞

如果您使用的是 Linux 或 Mac,则不需要 Go 程序:


$ echo "2019-09-30T04:17:02 - REQUEST-A

2019-09-30T04:18:02 - REQUEST-C

2019-09-30T04:19:02 - REQUEST-B

2019-09-30T04:20:02 - REQUEST-A

2019-09-30T04:21:02 - REQUEST-A

2019-09-30T04:22:02 - REQUEST-B" | awk '/REQUEST-A/{print $1}' | tee request.log

2019-09-30T04:17:02

2019-09-30T04:20:02

2019-09-30T04:21:02

然而,如果你真的想在 Go 中实现这个:


package main


import (

    "bufio"

    "fmt"

    "regexp"

    "strings"

)


const input = `

2019-09-30T04:17:02 - REQUEST-A

2019-09-30T04:18:02 - REQUEST-C

2019-09-30T04:19:02 - REQUEST-B

2019-09-30T04:20:02 - REQUEST-A

2019-09-30T04:21:02 - REQUEST-A

2019-09-30T04:22:02 - REQUEST-B

`


var scanner = bufio.NewScanner(strings.NewReader(input))


// Here comes the magic: We create an anonymous group containing all

// non-whitespace characters up to the first blank. Since it is

// a group, we can easily extract it later down the road.

var re *regexp.Regexp = regexp.MustCompile(`^(\S*) - REQUEST-A$`)


func main() {

    var res []string

    for scanner.Scan() {

        // We use re.FindStringSubmatch here, as it actually kills two

        // birds with one stone: We check wether it is REQUEST-A

        // and the anonymous group of the regexp contains what we are looking for.

        if res = re.FindStringSubmatch(scanner.Text()); len(res) > 0 {

            fmt.Println(res[1])

        }

    }

}

Run on playground



查看完整回答
反对 回复 2023-07-26
  • 3 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

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