RegExp匹配所有字符,直到两个连续的特殊字符(]])

RegExp匹配所有字符,直到两个连续的特殊字符(]]),regex,go,filebeat,Regex,Go,Filebeat,我试图找出一个(multiline.pattern)或两个(multiline.pattern&exclude_-line)正则表达式,以便将日志信息从filebeat发送到logstash。 写入日志的系统具有标准化的日志格式,如下所示 [2019-08-28 10:38:57 +0200][0000000000][Info][User][OLS][201][Some Logging Information] 为了匹配这一点,我构建了正则表达式(可能还需要一些改进:-) 不幸的是,当系统在调

我试图找出一个(multiline.pattern)或两个(multiline.pattern&exclude_-line)正则表达式,以便将日志信息从filebeat发送到logstash。 写入日志的系统具有标准化的日志格式,如下所示

[2019-08-28 10:38:57 +0200][0000000000][Info][User][OLS][201][Some Logging Information]
为了匹配这一点,我构建了正则表达式(可能还需要一些改进:-)

不幸的是,当系统在调试模式下运行时,日志结构会发生变化

[2019-05-24 09:58:39 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]
[2019-05-24 09:58:39 +0200][0000000000][Debug][External][RESTLM[HTDOC_REQUEST][Some Debug Loginformation]
[2019-05-24 09:58:34 +0200][0000000026][Debug][External][RESTLM][REST_RESPONSE][[45][HTTP/1.0 201 Created
    Server: Test/2019.3
    Pragma: no-cache
    Cache-control: no-cache
    Content-Type: text/xml
    Content-Length: 255

    <?xml version="1.0" encoding="utf-8"?>
    <Status><Repository><Path>D:/repository/tabfiles</Path><Version>4_0</Version><Fingerprint>p12uqocQM0gtaRieBldCix/CSSs=</Fingerprint></Repository><System>Running</System></Status>]]
[2019-05-24 09:58:34 +0200][0000000000][Debug][External][RESTLM][REST_REQUEST][[45][POST / HTTP/1.1
    Content-Type: text/xml; charset=utf-8
    Cache-Control: no-cache
    Pragma: no-cache
    User-Agent: Java/11.0.2
    Host: serverxyz:24821
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive
    Content-Length: 10

    <Status />]]
[2019-05-24 09:58:39+0200][0000000000][Debug][External][RESTLM][HTDOC\u REQUEST][一些调试登录信息]
[2019-05-24 09:58:39+0200][0000000000][Debug][External][RESTLM[HTDOC_请求][Some Debug login information]
[2019-05-24 09:58:34+0200][00000000 26][Debug][External][RESTLM][REST_RESPONSE][45][HTTP/1.0
服务器:测试/2019.3
Pragma:没有缓存
缓存控制:没有缓存
内容类型:text/xml
内容长度:255
D:/repository/tabfiles4_0p12uqocQM0gtaRieBldCix/CSSs=Running]]
[2019-05-24 09:58:34+0200][0000000000][Debug][External][RESTLM][REST_REQUEST][45][POST/HTTP/1.1
内容类型:text/xml;字符集=utf-8
缓存控制:没有缓存
Pragma:没有缓存
用户代理:Java/11.0.2
主机:serverxyz:24821
接受:text/html、image/gif、image/jpeg、*;q=.2、*/*;q=.2
连接:保持活力
内容长度:10
]]
我想排除那些在第三个字段中包含“Debug”的日志条目(多行)。 在我看来,普通日志和调试日志的主要区别在于第6个字段不是[\d*]。 在某些情况下,我认为这是我的问题,在Loginformation(最后一个日志字段)中有一个日志-看起来像[[[45][some text][other text]]

我要找的是一个正则表达式,它匹配一个独立于调试的完整日志条目,或者是普通日志条目。 还是两个表情 正常日志的第一次匹配
第二,匹配调试日志(并排除它们)

由于您只需匹配日志条目,而不捕获任何信息,请使用以下方法:

^\[\d{4}-\d{2}-\d{2}[\s\s]+?\]\]\]?$/gm

其思想是(通过使用
)惰性地捕获数据,直到在行尾遇到一个或两个
]


您的一些组是可选的,不确定是哪一组,但此表达式可以从以下内容开始:

^\[(\d{4})-(\d{2})-(\d{2})\s(\d{2}):(\d{2}):(\d{2})\s\+(\d{4})\]\[\d{10}\](\[[^\]]*\])?\[[^\]]*\]\[[^\]]*\]\[[^\]]*\]\[[^\]]*\](\[[\s\S]*?\])?$
或者

^\[(\d{4})-(\d{2})-(\d{2})\s(\d{2}):(\d{2}):(\d{2})\s\+(\d{4})\]\[(\d{10})\](\[([^\]]*)\])?\[([^\]]*)\]\[([^\]]*)\]\[([^\]]*)\]\[([^\]]*)\](\[([\s\S]*?)\])?$
如果您希望捕获括号中的数据


如果您希望简化/修改/探索表达式,将在的右上面板中进行解释。如果您愿意,还可以在中查看它与一些示例输入的匹配情况



如果要解析数据,可以选择类似bufio.Scanner的界面

package main

import (
    "bufio"
    "io"
    "log"
    "strings"
)

func main() {

    input := `
[2019-05-24 09:58:39 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]
[2019-05-24 09:58:40 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]
[2019-05-24 09:58:41 +0200][0000000026][Debug][External][RESTLM][REST_RESPONSE][[45][HTTP/1.0 201 Created
    Server: Test/2019.3
    Pragma: no-cache
    Cache-control: no-cache
    Content-Type: text/xml
    Content-Length: 255

    <?xml version="1.0" encoding="utf-8"?>
    <Status><Repository><Path>D:/repository/tabfiles</Path><Version>4_0</Version><Fingerprint>p12uqocQM0gtaRieBldCix/CSSs=</Fingerprint></Repository><System>Running</System></Status>]]
[2019-05-24 09:58:42 +0200][0000000000][Debug][External][RESTLM][REST_REQUEST][[45][POST / HTTP/1.1
    Content-Type: text/xml; charset=utf-8
    Cache-Control: no-cache
    Pragma: no-cache
    User-Agent: Java/11.0.2
    Host: serverxyz:24821
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive
    Content-Length: 10\]

    <Status />]]
`
    // input = `[2019-05-24 09:58:39 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]`

    src := strings.NewReader(input)
    parser := newScanner(src)
    for parser.Scan() {
        line := parser.Items()
        if len(line) > 2 && line[2] == "DEBUG" {
            continue
        }
        log.Printf("line %#v\n", line)
    }
    log.Println("done")
}

type scanner struct {
    *bufio.Scanner
    buf            []byte
    openedBrackets int
    lineDone       bool
    atEOF          bool
    lines          [][]string
    currentCols    []string
    currentCol     []byte
}

func newScanner(r io.Reader) *scanner {
    b := bufio.NewScanner(r)
    s := &scanner{
        Scanner:     b,
        buf:         make([]byte, 500),
        lines:       [][]string{},
        currentCols: []string{},
        currentCol:  []byte{},
    }
    b.Split(s.parse)
    return s
}

func (s *scanner) Scan() bool {
    for !s.lineDone {
        if s.Scanner.Scan() {
            s.lineDone = false
            return true
        } else if s.atEOF {
            return false
        }
    }
    return false
}

func (s *scanner) Items() []string {
    if len(s.lines) == 0 {
        return nil
    }
    return s.lines[len(s.lines)-1]
}

var (
    buf          = make([]byte, 500)
    eol          = []byte("\n")[0]
    bracketClose = []byte("]")[0]
    bracketOpen  = []byte("[")[0]
    backslash    = []byte("\\")[0]
)

func (s *scanner) parse(data []byte, atEOF bool) (advance int, token []byte, err error) {
    var d byte
    var i int
    var since int
    for i, d = range data {
        if d == bracketClose {
            if i > 0 && data[i-1] == backslash {
                continue
            }
            s.currentCol = append(s.currentCol, data[since+1:i]...)
            since = i
            s.openedBrackets--
            if s.openedBrackets == 0 {
                s.currentCols = append(s.currentCols, string(s.currentCol))
                s.currentCol = s.currentCol[:0]
            } else {
                s.currentCol = append(s.currentCol, d)
            }
        } else if s.openedBrackets == 0 && d == eol {
            line := make([]string, len(s.currentCols))
            copy(line, s.currentCols)
            s.lines = append(s.lines, line)
            s.currentCols = s.currentCols[:0]
            s.openedBrackets = 0
            s.lineDone = true
            return i + 1, data[i+1:], nil

        } else if d == bracketOpen {
            if i > 0 && data[i-1] == backslash {
                continue
            }
            since = i
            if s.openedBrackets > 0 {
                s.currentCol = append(s.currentCol, d)
            }
            s.openedBrackets++
        }
    }
    if atEOF {
        s.atEOF = true
        s.lineDone = true
        if len(s.currentCols) > 0 {
            line := make([]string, len(s.currentCols))
            copy(line, s.currentCols)
            s.lines = append(s.lines, line)
            s.currentCols = s.currentCols[:0]
            s.openedBrackets = 0
            s.lineDone = true
            return len(data) + 1, nil, nil
        }
        return len(data) + 1, nil, io.EOF
    }
    return len(data) + 1, nil, nil
}
主程序包
进口(
“布菲奥”
“io”
“日志”
“字符串”
)
func main(){
输入:=`
[2019-05-24 09:58:39+0200][0000000000][Debug][External][RESTLM][HTDOC\u REQUEST][一些调试登录信息]
[2019-05-24 09:58:40+0200][0000000000][Debug][External][RESTLM][HTDOC\u REQUEST][一些调试登录信息]
[2019-05-24 09:58:41+0200][00000000 26][Debug][External][RESTLM][REST_RESPONSE][45][HTTP/1.0
服务器:测试/2019.3
Pragma:没有缓存
缓存控制:没有缓存
内容类型:text/xml
内容长度:255
D:/repository/tabfiles4_0p12uqocQM0gtaRieBldCix/CSSs=Running]]
[2019-05-24 09:58:42+0200][0000000000][Debug][External][RESTLM][REST_REQUEST][45][POST/HTTP/1.1
内容类型:text/xml;字符集=utf-8
缓存控制:没有缓存
Pragma:没有缓存
用户代理:Java/11.0.2
主机:serverxyz:24821
接受:text/html、image/gif、image/jpeg、*;q=.2、*/*;q=.2
连接:保持活力
内容长度:10\]
]]
`
//输入=`[2019-05-24 09:58:39+0200][0000000000][Debug][External][RESTLM][HTDOC\u REQUEST][一些调试登录信息]`
src:=strings.NewReader(输入)
解析器:=newScanner(src)
对于parser.Scan(){
行:=parser.Items()
如果len(line)>2&&line[2]=“调试”{
持续
}
log.Printf(“行%#v\n”,行)
}
log.Println(“完成”)
}
类型扫描结构{
*扫描器
buf[]字节
开放式球拍
莱恩多布尔酒店
阿泰布尔酒店
行[][]字符串
currentCols[]字符串
currentCol[]字节
}
func新闻阅读器(读写器)*扫描仪{
b:=bufio.NewScanner(右)
s:=&扫描仪{
扫描仪:b,
buf:make([]字节,500),
行:[]字符串{},
currentCols:[]字符串{},
currentCol:[]字节{},
}
b、 拆分(s.parse)
返回s
}
func(s*扫描仪)扫描()布尔{
为了!s.lineDone{
如果是s.Scanner.Scan(){
s、 lineDone=false
返回真值
}如果s.atEOF{
返回错误
}
}
返回错误
}
func(s*扫描仪)项()[]字符串{
如果len(s.线)=0{
归零
}
返回s.lines[len(s.lines)-1]
}
变量(
buf=make([]字节,500)
eol=[]字节(“\n”)[0]
bracketClose=[]字节(“])[0]
括号打开=[]字节(“[”[0]
反斜杠=[]字节(“\\”[0]
)
func(s*扫描程序)解析(数据[]字节,atEOF bool)(高级整数,令牌[]字节,错误){
变量d字节
变量i int
自整型变量
对于i,d=范围数据{
如果d==括号闭合{
如果i>0&&data[i-1]==反斜杠{
持续
}
s、 currentCol=append(s.currentCol,数据[自+1:i]…)
因为=我
s、 开放式球拍--
如果s.openedBrackets==0{
s、 currentCols=append(s.currentCols,string(s.currentCol))
s、 currentCol=s.currentCol[:0]
}否则{
s、 currentCol=append(s.currentCol,d)
}
}否则,如果s.openedBrackets==0&&d==eol{
行:=make([]字符串,len(s.currentCols))
复制(行,s.currentCols)
s、 行=附加。
package main

import (
    "bufio"
    "io"
    "log"
    "strings"
)

func main() {

    input := `
[2019-05-24 09:58:39 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]
[2019-05-24 09:58:40 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]
[2019-05-24 09:58:41 +0200][0000000026][Debug][External][RESTLM][REST_RESPONSE][[45][HTTP/1.0 201 Created
    Server: Test/2019.3
    Pragma: no-cache
    Cache-control: no-cache
    Content-Type: text/xml
    Content-Length: 255

    <?xml version="1.0" encoding="utf-8"?>
    <Status><Repository><Path>D:/repository/tabfiles</Path><Version>4_0</Version><Fingerprint>p12uqocQM0gtaRieBldCix/CSSs=</Fingerprint></Repository><System>Running</System></Status>]]
[2019-05-24 09:58:42 +0200][0000000000][Debug][External][RESTLM][REST_REQUEST][[45][POST / HTTP/1.1
    Content-Type: text/xml; charset=utf-8
    Cache-Control: no-cache
    Pragma: no-cache
    User-Agent: Java/11.0.2
    Host: serverxyz:24821
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive
    Content-Length: 10\]

    <Status />]]
`
    // input = `[2019-05-24 09:58:39 +0200][0000000000][Debug][External][RESTLM][HTDOC_REQUEST][Some Debug Loginformation]`

    src := strings.NewReader(input)
    parser := newScanner(src)
    for parser.Scan() {
        line := parser.Items()
        if len(line) > 2 && line[2] == "DEBUG" {
            continue
        }
        log.Printf("line %#v\n", line)
    }
    log.Println("done")
}

type scanner struct {
    *bufio.Scanner
    buf            []byte
    openedBrackets int
    lineDone       bool
    atEOF          bool
    lines          [][]string
    currentCols    []string
    currentCol     []byte
}

func newScanner(r io.Reader) *scanner {
    b := bufio.NewScanner(r)
    s := &scanner{
        Scanner:     b,
        buf:         make([]byte, 500),
        lines:       [][]string{},
        currentCols: []string{},
        currentCol:  []byte{},
    }
    b.Split(s.parse)
    return s
}

func (s *scanner) Scan() bool {
    for !s.lineDone {
        if s.Scanner.Scan() {
            s.lineDone = false
            return true
        } else if s.atEOF {
            return false
        }
    }
    return false
}

func (s *scanner) Items() []string {
    if len(s.lines) == 0 {
        return nil
    }
    return s.lines[len(s.lines)-1]
}

var (
    buf          = make([]byte, 500)
    eol          = []byte("\n")[0]
    bracketClose = []byte("]")[0]
    bracketOpen  = []byte("[")[0]
    backslash    = []byte("\\")[0]
)

func (s *scanner) parse(data []byte, atEOF bool) (advance int, token []byte, err error) {
    var d byte
    var i int
    var since int
    for i, d = range data {
        if d == bracketClose {
            if i > 0 && data[i-1] == backslash {
                continue
            }
            s.currentCol = append(s.currentCol, data[since+1:i]...)
            since = i
            s.openedBrackets--
            if s.openedBrackets == 0 {
                s.currentCols = append(s.currentCols, string(s.currentCol))
                s.currentCol = s.currentCol[:0]
            } else {
                s.currentCol = append(s.currentCol, d)
            }
        } else if s.openedBrackets == 0 && d == eol {
            line := make([]string, len(s.currentCols))
            copy(line, s.currentCols)
            s.lines = append(s.lines, line)
            s.currentCols = s.currentCols[:0]
            s.openedBrackets = 0
            s.lineDone = true
            return i + 1, data[i+1:], nil

        } else if d == bracketOpen {
            if i > 0 && data[i-1] == backslash {
                continue
            }
            since = i
            if s.openedBrackets > 0 {
                s.currentCol = append(s.currentCol, d)
            }
            s.openedBrackets++
        }
    }
    if atEOF {
        s.atEOF = true
        s.lineDone = true
        if len(s.currentCols) > 0 {
            line := make([]string, len(s.currentCols))
            copy(line, s.currentCols)
            s.lines = append(s.lines, line)
            s.currentCols = s.currentCols[:0]
            s.openedBrackets = 0
            s.lineDone = true
            return len(data) + 1, nil, nil
        }
        return len(data) + 1, nil, io.EOF
    }
    return len(data) + 1, nil, nil
}