示例代码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex {
public static void main(String[] args) {
String data = "Shyam and you. You are 2.3 km away from home. Lakshmi and you. Ram and you. You are Mike. ";
Pattern pattern = Pattern.compile(
"\\s*((?:[^\\.]|(?:\\w+\\.)+\\w)*are.*?)(?:\\.\\s|\\.$)",
Pattern.DOTALL);
Matcher matcher = pattern.matcher(data);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
}
}
输出:
You are 2.3 km away from home.
You are Mike.
我在执行上面的代码时获得了预期的输出。 但问题是当用一些更大的字符串测试相同的正则表达式时,它显示溢出错误。 我搜索了同样的东西,并且知道正则表达式中的(A | B)*的交替导致问题。 有什么方法可以解决这个问题吗? 请帮忙。
答案 0 :(得分:3)
我试图重构你的正则表达式以避免回溯。你能试试这个正则表达式吗?
Pattern pattern = Pattern.compile("(?>[^.]|(?:\\w+\\.)+\\w)+\\sare\\s.*?(?>\\.\\s|\\.$)",
Pattern.DOTALL);
(?>group)
称为原子分组。
根据:http://www.regular-expressions.info/atomic.html
原子组是一个组,当正则表达式引擎退出时, 的
automatically throws away all backtracking positions remembered by any tokens inside the group
即可。原子组是非捕获的。语法 是(?>group)
。
答案 1 :(得分:1)
正如Pshemo在评论中明智指出的那样,你的问题可能是Catastrophic Backtracking的结果(由于所有那些嵌套的量词),而不是与输入字符串的长度有关。上面的链接提供了一个非常好的例子,说明为什么即使使用简短的输入字符串和看似简单的正则表达式也可以获得StackOverflowErrors
。
简而言之,这意味着在某些情况下,模式匹配器可以采用指数步数(与输入的长度相比)来确定匹配/不匹配。发生这种情况时,堆栈“溢出”,因为模式匹配递归过于深入。嵌套量词尤其常见,例如上面链接中的(x+x+)+y
,或者模式中的((?:\\w+\\.)+\\w)*
之一({1}}。
如果你解释一下你正在尝试编写一个正则表达式,我们很有可能会帮助你提出一个如果你给它不幸或恶意输入而不会爆炸的那个。
鉴于您对要求的评论,如果您完全避免使用正则表达式,则可以通过 way 来解决这个问题。只需在分隔符周围分割输入(在您的情况下为". "
),然后在每个结果中搜索关键字。正如一些评论者提到的那样,无论如何分割你的数据通常更安全,特别是如果它的大小未知。
String[] sentences = data.split("\\. ");
for (String sentence : sentences) {
if (sentence.contains("are")) {
System.out.println(sentence.concat(". "));
}
}