首页 > 解决方案 > 正则表达式标记日志行

问题描述

我有一个日志行如下:

[2021-03-10 00:13:32.901] [DefaultDispatcher-worker-2 @coroutine#3] [DEBUG] [4231c006d9083a302fce59d5f0957226] [42c5ac3c0acfc68d] [GreeterImpl] 你好约翰

它是 6 个文本块,[]然后是其余的。我正在寻找一个正则表达式来提取其中的文本[],以及最后。其中的文本块[]可以为空。

我试过(?:\[([^\[\]]*)\])+([^\[\]]+)了,但它只匹配[]. 我也尝试过(?:(?<=\[)[^\[\]]*(?=\]))+([^\[\]]+),但这与任何东西都不匹配。

FWIW,正则表达式将在 Java 中实现。

标签: javaregexregex-lookaroundsregex-group

解决方案


简短的编辑:这个稍微简单的正则表达式也适用:

(?:(?<=\[)[^\[\]]*)|(?:(?<=\])[^\[\]]*$)

我从你自己的评论中得到了它。

原始答案如下。

TL;博士

(?:(?<=^\[| \[)[^\[\]]*)|(?:(?<=\] )[^\[\]]*$)

解释:有两个部分|,用“或”隔开。

  1. 第一部分(?:(?<=^\[| \[)[^\[\]]*)匹配方括号内的内容。[^\[\]]*接近结尾的匹配最长可能的字符既不是[也不是](?<=^\[| \[)要求它前面有字符串的开头和 a[ [. 最后,我将整个内容放入一个非捕获组中,以确保后视优先于|.
  2. 第二部分,(?:(?<=\] )[^\[\]]*$)匹配日志行末尾方括号之外的内容(Hello John在示例中)。这次非括号的运行必须] 在行尾之前和之后。

看看它的实际效果:

  1. 在我构建它的 regex101上

  2. 在 Java 中:

    String logLine = "[2021-03-10 00:13:32.901]"
            + " [DefaultDispatcher-worker-2 @coroutine#3] [DEBUG]"
            + " [4231c006d9083a302fce59d5f0957226] [42c5ac3c0acfc68d]"
            + " [GreeterImpl] Hello John";
    
    Matcher m = Pattern
            .compile("(?:(?<=^\\[| \\[)[^\\[\\]]*)|(?:(?<=\\] )[^\\[\\]]*$)")
            .matcher(logLine);
    while (m.find()) {
        System.out.println(m.group());
    }
    

输出是:

2021-03-10 00:13:32.901
DefaultDispatcher-worker-2 @coroutine#3
DEBUG
4231c006d9083a302fce59d5f0957226
42c5ac3c0acfc68d
GreeterImpl
Hello John

一个不同的想法:String.split()

    String[] tokens = logLine.split("\\] \\[|\\] (?!\\[)");
    assert tokens[0].startsWith("[") : logLine;
    tokens[0] = tokens[0].substring(1);

    for (String token : tokens) {
        System.out.println(token);
    }

输出和以前一样。

我要么分裂要么] [] 跟随[最后一次分裂)。它使第一个[完好无损,所以我必须单独删除它,这不太好。否则,我发现它比其他解决方案更容易理解。


推荐阅读