不幸的是,我还不是一名正则表达式专家,因此遇到以下问题: 假设我有一个包含多个链式异常的Java堆栈跟踪,我想要达到的是从&#34开始提取最后一行;由"引起。
javax.servlet.ServletException: Something bad happened
at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)
.
.
Caused by: com.example.myproject.MyProjectServletException
.
.
Caused by: This is the line I want to capture
到目前为止,我发现Caused by.(?!.*Caused by)
基于负向前瞻,给了我最后一个"由"引起删除所有标签和空格后,(但不是其余部分)。有没有办法让我得到我想要的结果?如果必须删除所有空格,那对我来说没问题。谢谢!
答案 0 :(得分:5)
以下是基于贪心量词的非基于外观的解决方案:
\A[\s\S]*\nCaused by:\s*(?<LastCausedBy>.*)\Z
模式匹配
\A
- 字符串的开头[\s\S]*
- 尽可能多的任意0个字符(实际上,抓住所有文本到最后然后向后移动 - 回溯 - 找到最后一个......)\nCaused by:
- 换行后跟Caused by:
\s*
- 0+空白符号(?<LastCausedBy>.*)
- 除换行符之外的任何0 +字符(捕获到LastCausedBy
命名组\Z
- 字符串结尾在Grok Debugger测试:
答案 1 :(得分:1)
我建议您将substring
与lastIndexOf
结合使用以获得Caused by
的最后一次出现
就像那样:
String lastCaused = yourStacktraceAsString.substring(yourStacktraceAsString.lastIndexOf("Caused by"));
答案 2 :(得分:1)
这可以通过正则表达式来完成,但在这种情况下,它可能更简单,只需要子串。假设您的异常堆栈跟踪是在String调用ex:
中捕获的ex.substring(ex.lastIndexOf('Caused by:'))
答案 3 :(得分:1)
谢谢@Pshemo,你的想法让我走向了解决方案。经过数小时的反复试验,以下模式按预期工作:
(?m)(Caused by:)(?![\s\S.]*Caused by).*$
这与评论中的建议非常接近!
答案 4 :(得分:0)
正则表达式是棘手的,易碎的,难以阅读和维护。消极的前瞻使情况变得更糟。仅在需要时使用它们。我建议只需迭代text.split("\n")
,查找以Caused by:
开头的行,并将其保留在循环的末尾。