当前位置: 首页 > 知识库问答 >
问题:

尝试在java中使用regex时堆栈溢出

戈念
2023-03-14

我读了一些关于如何优化正则表达式的文章,但是没有一个答案(更少的组,使用{X,Y}而不是*)似乎阻止了我的正则表达式获得堆栈溢出错误。

我正在尝试通过文件进行动态搜索。假设我正在一个相当大(2-4MB)的文件中搜索“我打赌你找不到我”。我的正则表达式生成器将生成正则表达式:

i(?:.|\s)*?bet(?:.|\s)*?you(?:.|\s)*?cannot(?:.|\s)*?find(?:.|\s)*?me

这个正则表达式的想法是,无论单词之间有什么字符或空格,它都能找到准确的短语。然而,当我尝试使用:

Pattern p = Pattern.compile(generatedRegex, Pattern.MULTILINE);
Matcher m = p.matcher(fileContentsAsString);
while (m.find()) {
System.out.println(m.group())
}

我遇到堆栈溢出错误。我知道正则表达式使用递归,但它似乎并没有正则表达式那么糟糕。有没有办法优化这个正则表达式?谢谢

回答:

Pattern p = Pattern.compile("i(?:.*)bet(?:.*)you(?:.*)cannot(?:.*)find(?:.*?)me", Pattern.DOTALL);

是我最终使用的模式/正则表达式。看起来很快,不再出现堆栈溢出异常

共有1个答案

戎志勇
2023-03-14

我认为你得到了很多回溯,因为你不情愿的限定符(*?).防止回溯的一种方法是使用原子分组(?

根据评论,你也更喜欢只捕捉离“下注”最近的“i”,以减少整体匹配的长度。因为你想得到最接近其余单词的“i”,那么在我为单词2添加了否定性前瞻的地方,你也应该为单词1添加一个否定性前瞻,就在它旁边。换句话说,(?!打赌)会变成(?!i)(?!打赌)(?!i|bet).我已经编辑了下面的代码来包含这个需求。

String fileContentsAsString = "ii ... bet ... you, ibetyouyou";
String regex = "i(?>(?!i|bet).)*+bet(?>(?!you).)*+you";
Pattern p = Pattern.compile(regex, Pattern.DOTALL);
Matcher m = p.matcher(fileContentsAsString);
while (m.find()) {
    System.out.println(m.group());
}

输出:

我打赌你

ibetyou

解释(来源):

“不情愿的量词的工作方式是,每次它应该尝试匹配时,它首先尝试让正则表达式的下一部分匹配。因此,它实际上是在每次迭代的开始进行前瞻,这可能会变得非常昂贵,尤其是当量化的部分每次迭代只匹配一个字符时,比如。*?"

 类似资料:
  • 问题内容: 您可以尝试/捕获Java中的堆栈溢出异常吗?它似乎在向任一方向投掷自己。当程序溢出时,我想“惩罚”该值。 问题答案: 似乎可以工作:

  • 我基于Maged M.Michael和Michael L.Scott的《简单、快速、实用的非阻塞和阻塞并发队列算法》中指定的算法实现了一个无锁队列(有关算法,请跳到第4页) 我在上使用了原子操作,如等。 当只在一个线程中使用队列时,一切都很好,但是当从不同的线程中使用它时,我会得到堆栈溢出异常。 不幸的是,我无法追查问题的根源。似乎当一个<code>shared_ptr</code>超出范围时,它

  • 问题内容: 我想使用rxjava Observable处理翻新中的分页。我听了另一个问题的建议。 我有100多个页面需要获取,但是链在第20页左右失败,并且在logcat中使用以下日志停止了对可观察对象的任何进一步订阅 有人知道为什么会发生这种情况吗? 更新: 我知道这是由于递归而发生的,但是有没有更优雅的方式来处理带有翻新和rxjava的分页? 问题答案: 因此,鉴于我回答了您引用的原始问题,我

  • im执行此任务,并不断在线程“main”java.lang.RuntimeException中获得异常:Stack.pop(postfix.java:74)、postfix.eval(postfix.java:221)和postfix.main(postfix.java:112)处的堆栈下溢 我不知道为什么我看着堆栈并且写得正确,我不明白为什么它在(3*4)/5时弹出的问题

  • 问题内容: 我正在运行一个用Java在Eclipse中编写的程序。对于很大的输入,该程序具有很深的递归级别。对于较小的输入,程序运行正常,但是在给出较大的输入时,出现以下错误: 可以通过增加Java堆栈大小来解决此问题,如果可以,那么如何在Eclipse中做到这一点? 更新: @乔恩·斯基特 该代码递归地遍历解析树以建立数据结构。因此,例如,代码将使用解析树中的一个节点来做一些工作,并在该节点的两

  • 我有一个执行快速排序的应用程序。在我开始给它一些更大的数字(我第一次得到它是10000000)之前,它工作得很好。我知道是由递归引起的,但我不明白为什么我的应用程序会因此而崩溃。如有任何建议,将不胜感激。这是我的密码: