为什么java(使用Matcher.find())找不到最长的匹配?
regex = "ab*(bc)?"
输入“abbbc”时,正则表达式会找到“abbb”,而不是“abbbc”,它也匹配并且更长。 有没有办法强制它匹配最长的字符串?
答案 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)?
。