Java 用于提取异常消息字段的正则表达式

Java 用于提取异常消息字段的正则表达式,java,regex,Java,Regex,我设计了正则表达式来匹配异常消息字段 ^.*\s([^:,\s]+):\s+([^:]+)\sat\s+\S+\((\w+)\.\w+:(\d+)\)$ 它只匹配几个字段 测试字符串是: ERROR java.lang.NullPointerException: Sample Java Logback Exception at Sample.errorLevel3(Sample.java:35) at Sample.errorLevel4(Sample.java:34) at Sampl

我设计了正则表达式来匹配异常消息字段

^.*\s([^:,\s]+):\s+([^:]+)\sat\s+\S+\((\w+)\.\w+:(\d+)\)$
它只匹配几个字段

测试字符串是:

ERROR java.lang.NullPointerException: Sample Java Logback Exception

at Sample.errorLevel3(Sample.java:35)

at Sample.errorLevel4(Sample.java:34)

at Sample.errorLevel5(Sample.java:30)

at Sample.errorLevel6(Sample.java:3)
找到匹配项:

java.lang.NullPointerException

Sample Java Logback Exception

Sample

35
预期匹配:

java.lang.NullPointerException 

Sample Java Logback Exception

Sample.errorLevel3

Sample.java

35

Sample.errorLevel4

Sample.java

34

Sample.errorLevel5

Sample.java

30

Sample.errorLevel6

Sample.java

3

有谁有更好的正则表达式来匹配异常消息的字段吗?

您不能有与正则表达式匹配的动态数目。你的目标必须在两步之内实现

步骤1-提取错误标题:

ERROR ([^:]+): (.*)

步骤2-提取错误信息

(?:\s+at ([^(]+)\(([^:]+):(\d+))\)

任何时候使用()都会创建一个捕获组。因此,在正则表达式中,您有4个捕获组,从中可以提取数据

第一个捕获了异常名称,我相信它是正确的,尽管我不知道所有的可能性

第二个捕获消息。我认为它应该是可选的,所有的异常都有消息吗?包括定制的吗?除此之外,这似乎是正确的。我只会在后面加上一美元,以确保它到达终点

我认为,问题始于第三个捕获组,它应该捕获方法名称。将此部分:
\S+\(\w+)\。\w+:(\d+)$
更改为
([\w.]+\w+)\([\w.]+\w+:(\d+)$

添加的3个捕获组用于方法名、文件名和行号

另外,添加一个+以允许您捕获多个错误行

最后一个正则表达式是:
^.*\s([^:,\s]+):\s+([^:]+)$(?:\s*at\s+([\w\.]+\w+)([\w\.]+\w+:(\d+)+

然而,正如Doro所指出的,您不能用同一个正则表达式捕获多个部分匹配,这就是您试图使用错误行所做的

您应该分成两个正则表达式:
^..*\s([^:,\s]+):\s+([^:]+)$
\s*at\s+([\w\.]+\w+)([\w\.]+\w+):(\d+)+

除此之外,我不确定java正则表达式是否正确,但在C#中,我们可以命名捕获组,以便稍后使用(?your group here)语法轻松获取它们。我将搜索它是如何在Java中完成的,并在这里发布

编辑:要查看Java如何支持命名组,请参阅答案


您可以测试正则表达式的一个好站点是regex101.com。

您可以匹配第一行,然后使用来匹配以下行:

Regex

(?:^.*\s([^:,\s]+):\s+([^:\n]+)|\G(?!\A))\s*at\s+(\S+)\((\w+\.\w+):(\d+)\)$
其中:

  • 第一场比赛
    • ^.*\s([^:,\s]+):\s+([^:\n]+)
      异常描述
    • \G(?!\A)
      上次匹配的结束
  • 然后
    \s*at\s+
    literal
    at
    被空格包围(包括换行符)
  • (\S+)
    组3中的错误级别
  • \((\w+\.\w+)
    组4中的源
  • :(\d+)\$
    组5中的行
代码

String text = String.join("\n",
    "ERROR java.lang.NullPointerException: Sample Java Logback Exception",
    "at Sample.errorLevel3(Sample.java:35)",
    "at Sample.errorLevel4(Sample.java:34)",
    "at Sample.errorLevel5(Sample.java:30)",
    "at Sample.errorLevel6(Sample.java:3)"
);
String pattern = "(?:^.*\\s([^:,\\s]+):\\s+([^:\\n]+)|\\G(?!\\A))\\s*at\\s+(\\S+)\\((\\w+\\.\\w+):(\\d+)\\)$";
Pattern regex = Pattern.compile(pattern, Pattern.MULTILINE);
Matcher m = regex.matcher(text);
int matchNum = 0;

//Loop matches
while (m.find())
{
    matchNum++;

    // Loop groups
    for (int i = 1; i <= m.groupCount(); i++) 
    {
        if (m.group(i) != null) {
            System.out.println("Match " + matchNum + " - Group " + i + ": " + m.group(i));
        }
    }
}

为什么不使用error对象来获取所需的数据呢?好吧,您没有将缺少的部分放入一个组中(在括号中),因此它们不会被报告。您可以创建
(?组)
,并在代码中将它们作为
matcher.group(groupName)
Match 1 - Group 1: java.lang.NullPointerException
Match 1 - Group 2: Sample Java Logback Exception
Match 1 - Group 3: Sample.errorLevel3
Match 1 - Group 4: Sample.java
Match 1 - Group 5: 35
Match 2 - Group 3: Sample.errorLevel4
Match 2 - Group 4: Sample.java
Match 2 - Group 5: 34
Match 3 - Group 3: Sample.errorLevel5
Match 3 - Group 4: Sample.java
Match 3 - Group 5: 30
Match 4 - Group 3: Sample.errorLevel6
Match 4 - Group 4: Sample.java
Match 4 - Group 5: 3