Java正则表达式matcher.find偶尔会失败

时间:2012-05-31 11:15:10

标签: java regex

我有regexp解析模板中所用的freemarker宏的所有名称(例如来自<@macroName />我只需要macroName)。模板通常非常大(圆形3万个字符)。 带有正则表达式的Java代码如下:

Pattern pattern = Pattern.compile(".*?<@(.*?)[ /].*?", 
                                  Pattern.DOTALL | Pattern.UNIX_LINES);
Matcher matcher = pattern.matcher(inputText);
while(matcher.find()){
    //... some code
}

但有时我会得到这个例外:

java.util.regex.Pattern$Curly.match1(Pattern.java:3814)
java.util.regex.Pattern$Curly.match(Pattern.java:3763)
java.util.regex.Pattern$Start.match(Pattern.java:3072)
java.util.regex.Matcher.search(Matcher.java:1116)
java.util.regex.Matcher.find(Matcher.java:552)
...

有人知道它为什么会发生,或者任何人都可以确定我使用的正则表达式是否得到了很好的优化? 谢谢

2 个答案:

答案 0 :(得分:3)

对于<@macro macroName />,你的正则表达式看起来有点复杂。要么<@macro macroName />没有描述的事情(特殊情况),要么正则表达式都在努力。尝试:

<@macro\s+(\S+)\s+/>

您现在应该拥有组#1中的宏名称。

答案 1 :(得分:1)

您可以删除前导.*?,因为您不需要在匹配之前/之间使用文本。正则表达式引擎将负责扫描下一场比赛,它将比你正在做的更有效率。只需给它标签本身的模式,然后就可以了。

你可以摆脱尾随 .*?,因为它永远不会做任何事情。想一想:它不情愿地试图匹配零个或多个任何角色。这意味着它试图做的第一件事就是什么都不匹配。该尝试将成功(它总是可以匹配任何东西),所以它永远不会尝试消耗更多的字符。

你可能想要这样的东西():

<@(\w+)[\s/]

......或者说Java:

Pattern p= Pattern.compile("<@(\\w+)[ /]");

您不需要DOTALL(无点)或任何其他修饰符。