1

我正在尝试在第二级下的以下文本中解析“餐饮:”后面的数字。所以应该返回'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:是任何文本,直到找到为止。这个演示说明了我遇到的两个问题。使用的正则表达式是:(?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b)

  1. 在您删除最后一行包含Laundry: 1. 这是由于比赛太多还是其他原因造成的?
  2. 删除该行后,正则表达式仅捕获 .. 下的最后一个匹配项,OTHER LEVEL返回 '2' 而不是 .. 下的匹配项SECOND LEVEL

有时Dining:将不存在SECOND LEVEL,因此不应返回任何内容。

什么是只捕获SECOND LEVEL'Dining:号的正则表达式,如果它不存在则不返回任何内容?首选正则表达式,如果可能,不要在 Java 中循环。谢谢

4

2 回答 2

2

使用基于负前瞻的正则表达式。

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

演示

于 2015-12-27T00:55:35.677 回答
1

我所知道的灾难性回溯的最佳示例(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$]*)
于 2015-12-27T01:13:18.110 回答