java正则表达式找不到最长匹配

时间:2011-01-19 17:56:35

标签: java regex

为什么java(使用Matcher.find())找不到最长的匹配?

regex = "ab*(bc)?"

输入“abbbc”时,正则表达式会找到“abbb”,而不是“abbbc”,它也匹配并且更长。 有没有办法强制它匹配最长的字符串?

4 个答案:

答案 0 :(得分:5)

(bc)是一个精确的字符串,因为b *是贪婪的,所以找不到它,但是(bc)? 是最后一个'b'之后超过的匹配是可选的。 你可能想要这样的东西:ab*[bc]?但这个意义很有意义,所以可能ab*c?。如果这个正则表达式代表更精细的东西,你应该发布这些例子。

以下是正则表达式引擎的看法:

Compiling REx "ab*(bc)?"
Matching REx "ab*(bc)?" against "abbbc"
   0 <> <abbbc>              |  1:EXACT <a>(3)
   1 <a> <bbbc>              |  3:STAR(6)
                                  EXACT <b> can match 3 times out of 2147483647...
   4 <abbb> <c>              |  6:  CURLYM[1] {0,1}(16)
   4 <abbb> <c>              | 10:    EXACT <bc>(14)
                                      failed...
                                    CURLYM trying tail with matches=0...
   4 <abbb> <c>              | 16:    END(0)
Match successful!

Compiling REx "ab*[bc]?"
Matching REx "ab*[bc]?" against "abbbc"
   0 <> <abbbc>              |  1:EXACT <a>(3)
   1 <a> <bbbc>              |  3:STAR(6)
                                  EXACT <b> can match 3 times out of 2147483647...
   4 <abbb> <c>              |  6:  CURLY {0,1}(19)
                                    ANYOF[bc] can match 1 times out of 1...
   5 <abbbc> <>              | 19:    END(0)
Match successful!

答案 1 :(得分:1)

这些部分从左到右贪婪地匹配。所以b*贪婪地匹配会导致(bc)?失败,这很好,因此匹配器永远不会回溯以尝试更短的b*

也许ab*?(?:(?![bc])|(bc))可以做你想要的。

答案 2 :(得分:1)

其他人帮助改善了正则表达式;但只是强调答案是“因为它确实贪婪匹配”。也就是说,你得到的匹配是根据算法得到的匹配(基本上从左到右进行最长的子匹配)。

答案 3 :(得分:1)

如果您的表达看起来如此,并且您不关心分组,则可以将其重写为ab+c?

如果表达式实际上更复杂并且(bc)是必不可少的,那么您可以使用负面预测,如下所示,我认为它比Mike Samuel的解决方案更优雅:ab*(?!c)(bc)?