【问题标题】:Regex for extract the Exception Message fields用于提取异常消息字段的正则表达式
【发布时间】:2015-11-06 21:35:55
【问题描述】:

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

^.*\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

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

【问题讨论】:

  • 为什么不直接使用error对象来获取你需要的数据呢?
  • 嗯,你没有把缺失的部分放在一个组中(在括号中),所以它们没有被报告。

标签: java regex


【解决方案1】:

你可以先匹配第一行,然后用\G assertion匹配下面几行:

正则表达式

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

地点:

  • 第一个 non-capturing group 匹配
    • ^.*\s([^:,\s]+):\s+([^:\n]+)异常说明
    • \G(?!\A)最后一场比赛结束
  • 然后是 \s*at\s+ 文字 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));
        }
    }
}

输出

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

ideone demo

【讨论】:

    【解决方案2】:

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

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

    第二个捕获消息。我相信它应该是可选的,所有异常都有消息吗?包括定制的?除此之外,它似乎是正确的。我只会在后面添加一个 $ 以确保它到达行尾。

    我相信问题始于应该捕获方法名称的第三个捕获组。更改这部分:\S+\((\w+)\.\w+:(\d+)\)$([\w.]+\w+)\(([\w.]+\w+)\:(\d+)\)$

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

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

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

    但是,正如 Doro 所指出的,您无法使用相同的正则表达式捕获多个 部分 匹配项,这正是您试图对错误行执行的操作。

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

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

    编辑:要了解 Java 如何支持命名组,请参阅 this 答案。

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

    【讨论】:

    • 您可以创建(?&lt;named&gt;groups) 并在代码中将它们引用为matcher.group(groupName)
    【解决方案3】:

    您不能使用正则表达式获得动态匹配数。您的目标必须在两个步骤内达到。

    第 1 步 - 提取错误标头:

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

    https://regex101.com/r/eQ3rI5/1

    第 2 步 - 提取错误信息

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

    https://regex101.com/r/eQ3rI5/2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多