为什么不呢?在这种模式中作为可选的重复说明符工作?

时间:2010-07-22 17:25:27

标签: java regex

我正在尝试匹配像

这样的输入
<foo>
<bar>
#####<foo>
#####<bar>

我尝试了#{5}?<\w+>,但它与<foo><bar>不匹配。

这种模式有什么问题,如何解决?

2 个答案:

答案 0 :(得分:11)

On ? for optional vs reluctant

Java正则表达式中的?元字符(以及其他一些版本)可能有两种截然不同的含义,具体取决于它出现的位置。紧跟重复说明符后,?是一个不情愿的量词,而不是“零或一”/“可选”重复说明符。

因此,#{5}?并不意味着“可选地匹配5 #”。事实上它说“不情愿地匹配5 #”。尝试匹配“确切地说5,但尽可能少”,这可能没有多大意义,但这实际上就是这种模式的含义。


分组救援!

解决此问题的一种方法是将可选模式分组为(…)?。这样的事情应该适用于这个问题:

(#{5})?<\w+>

现在?没有立即跟随重复说明符(即*+?{…});它遵循用于分组的结束括号。

或者,您也可以在这种情况下使用非捕获组(?:…)

(?:#{5})?<\w+>

这实现了相同的分组效果,但没有捕获到\1

参考

相关问题


奖励材料:??

怎么样?

值得注意的是,您可以使用??来勉强匹配可选项目!

    System.out.println("NOMZ".matches("NOMZ??"));
    // "true"

    System.out.println(
          "NOM NOMZ NOMZZ".replaceAll("NOMZ??", "YUM")
    ); // "YUM YUMZ YUMZZ"

请注意,Z??是可选的Z,但它不情愿地匹配。 "NOMZ"完整matches模式NOMZ??,但在replaceAllNOMZ??只能与"NOM"匹配,而不必采取Z可选NOMZ?,即使它在那里。

相比之下,Z会贪婪地匹配可选的 System.out.println( "NOM NOMZ NOMZZ".replaceAll("NOMZ?", "YUM") ); // "YUM YUM YUMZ" :如果它在那里,它就会接受它。

matches

相关问题

答案 1 :(得分:2)

将您的#匹配放在子模式中:

(#{5})?<\w+>