正则表达式捕获

时间:2015-12-27 00:48:47

标签: java regex regex-lookarounds regex-greedy capture-group

我正在尝试解析在下面的文章“SECOND LEVEL”下面的“Dining:”后面的数字。所以应该返回'666'。

    MAIN LEVEL
        Entrance: 11
        Dining: 33

    SECOND LEVEL
        Entrance: 4444
        Living: 5555
        Dining: 666

    THIRD LEVEL
        Dining: 999
        Kitchen: 000
        Family: 33332

如果我使用类似(?:\bDining:\s)(.*\b)的内容,则会捕获MAIN下的第一个匹配项。我正在尝试在正则表达式中指定SECOND LEVEL,然后是重复模式:新行,多个空格,然后是任何文本,直到找到Dining:This demo说明了我遇到的两个问题。使用的正则表达式是:(?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b)

  1. 出现“灾难性回溯”错误,直到删除包含Laundry: 1的最后一行。这是由太多比赛引起的吗?
  2. 删除该行后,正则表达式仅捕获OTHER LEVEL下的最后匹配..返回'2'而不是SECOND LEVEL下的匹配。
  3. 有时Dining:下不存在SECOND LEVEL,因此不应返回任何内容。

    什么是只捕获SECOND LEVEL的{​​{1}}号码的正则表达式,如果它不存在则返回什么?直接正则表达式首选,如果可能的话,在Java中没有循环。感谢

2 个答案:

答案 0 :(得分:2)

使用基于正面的负面预测。

"(?m)^\\s*\\bSECOND LEVEL\\n(?:(?!\\n\\n)[\\s\\S])*\\bDining:\\s*(\\d+)"

DEMO

答案 1 :(得分:1)

我所知道的灾难性回溯from here的最佳示例是(x+x+)+y。也就是说,它无法找出包含x的捕获组的正确边界,因为有太多方法可以将它们分开。

xxxxy是前两个+一次,第三个两次,或者前两次和第三次一次,或者第一次三次,另一次一次和最后一次。正如你所看到的那样危险!

(?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b)注意(\n\s+.*)*  .*与之前的\n\s结合使用后,可能会成为一场噩梦,并附带*。它应该被重写(\n\s+[^\s\n][^\n]*)*这可以确保每个量词在下一次开始之前结束,从而最大限度地减少回溯。

考虑到这种想法,我提出了以下正则表达式来匹配你的字符串:

(?<=SECOND LEVEL\n)(?:\s+(?:[^\s\n:][^\n:]*):[^\n]*)*\s+Dining:\s*([^\s\n][^\n$]*)
相关问题