我不知道为什么,但是当我尝试运行这个程序时,看起来该程序将永远运行。
package fjr.test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test3 {
public static void main(String[] args){
String regex = "dssdfsdfdsf wdasdads dadlkn mdsds .";
Pattern p = Pattern.compile("^([a-zA-Z]+ *)+$");
Matcher match = p.matcher(regex);
if(match.matches()){
System.out.println("Yess");
}else{
System.out.println("No.. ");
}
System.out.println("FINISH...");
}
}
我需要做的是匹配包含一串只用空格
分隔的单词的模式答案 0 :(得分:5)
您的计划可能遇到了所谓的灾难性回溯。
快速复习:正则表达式如何工作:状态机始终从左向右读取,必要时回溯。
在左侧,我们有我们的模式:
/^([a-zA-Z]+ *)+$/
这是匹配的字符串:
dssdfsdfdsf wdasdads dadlkn mdsds .
从regex101调试器中,你的正则表达式需要78540步才能失败。这是因为您使用了贪婪和不占有(回溯)的量词。
...长话短说,因为输入字符串无法匹配,正则表达式中的每个量词都会导致无限回溯 - 每个字符都从{{1}释放然后+
,然后两个,然后从*
释放一个组,以便更多地回溯。
以下是您应遵循的一些解决方案:
如果你修改你的表达式,你会发现该模式在逻辑上与:
相同()+
这使用逻辑归纳的步骤来减少楼上的正则表达式以更快地匹配远,现在是97步!
正如我所提到的,/^[a-zA-Z]+( +[a-zA-Z]+)*$/
是邪恶的,因为它以强烈的方式回溯。我们是Java,我们能做什么?
此解决方案仅适用于/^([a-zA-Z]+ *)+$/
和[a-zA-Z]
匹配不同的项目。我们可以使用占有团体!
这些简单的“/^([a-zA-Z]++ *+)++$/
^ ^ ^
”表示“如果我们从这里失败,我们就不会回溯”。这是一个非常有效的解决方案,并且不再需要回溯。每当你有两个不同的组,其间有量词时,请使用它们。如果您需要一些有效性的证据,这是我们的记分卡:
另请阅读:
在线演示:
答案 1 :(得分:2)
这会终止,但确实需要10秒左右。一些观察:
将正则表达式中的*更改为+(我相信其实就是你想要的)会让它变快。我认为在该位置选择0个字符可以扩展状态空间。 我会用:
^(\ w + +)* \ w + $"
这意味着一堆(字空间),后跟一个字。反对你的例子,它很快
答案 2 :(得分:1)
您可以使用此正则表达式将所有单词与空格匹配或不匹配。
<强>样品:强>
Pattern p = Pattern.compile("([a-zA-Z ]+)");
答案 3 :(得分:0)
有趣的现象。这与贪心量词的行为有关。性能。
根据您的模式^([a-zA-Z]+ *)+$
和您的输入"dssdfsdfdsf wdasdads dadlkn mdsds ."
,该输出不符合您的输入,但是,java正则表达式将回溯^([a-zA-Z]+ *)+
的所有可能性,(见下文)例子)然后获得不匹配的结果。
(dssdfsdfdsf )(wdasdads )(dadlkn )(mdsds )
(dssdfsdfdsf )(wdasdads )(dadlkn )(mdsd)(s )
(dssdfsdfdsf )(wdasdads )(dadlkn )(mds)(ds )
...
(d)(s)(s)(d)(f)(s)(d)(f)(d)(s)(f )(w)(d)(a)(s)(d)(a)(d)(s )(d)(a)(d)(l)(k)(n )(m)(d)(s)(d)(s )
...
(dssdfsdfdsf )
...
(d)
回溯可能超过200,000,000次 我有点好奇为什么java-regex可以做一些性能改进,因为在第一次尝试之后,它发现了epxected char是&#39;。&#39;而不是&#39; $& #39;然后任何进一步的回溯都不会成功。做回溯是没用的。
因此,当我们定义循环模式时,我们需要更多地注意内部循环模式(例如:在您的示例中为[a-zA-Z]+ *
),而不是使它与许多情况匹配。否则,整个Loop的回溯数将是巨大的
另一个类似的例子(比你的情况更糟糕):
模式:&#34;(。+)* A&#34;
输入:&#34; abcdefghijk lmnopqrs tuvwxy zzzzz A&#34; - 这么快
输入:&#34; abcdefghijAk lmnopqrs tuvwxy zzzzz&#34; - 不错,等一会儿
输入:&#34; aAbcdefghijk lmnopqrs tuvwxy zzzzz&#34; - 似乎无限。 (实际上,不是,但我没有耐心等待它的完成。)