Lookahead正则表达式

时间:2012-01-26 23:46:00

标签: regex boost

我希望匹配以下模式

(1)

10digits sometext (例如1235873490 ABCD EFGK)

在可能具有上述模式的文本中,以及与此类似的非常相似的模式

(2)

10digits sometext decimal_number (例如9835873490 VBGF XMF 23.233)

如何编写正则表达式以仅匹配模式(1)并忽略模式(2)?

我使用类似的东西看过负面的前瞻:

(\d{10})\s*([A-Za-z0-9]+(?:\s+[A-Za-z0-9]+)(?:\s+[A-Za-z0-9]+))\s*(?!(\d+.\d+))

但无法让它发挥作用。有任何想法吗?顺便说一句,我使用的是c ++ boost :: regex。

1 个答案:

答案 0 :(得分:2)

首先,从简单的版本开始:

(\d{10}         # 10 digits
    (?:\s+\w+)+)  # some text, separated by spaces,
                  # at least one time
(?!\s*\d+\.\d+) # not followed by a decimal number

为简单起见,我将[A-Za-z0-9]更改为\w,并允许其按照自己的意愿进行多次。

但是,这也会匹配第二个字符串 - 它会在最后吞噬23,然后看到它后面没有小数点(后跟“.23”),所以它会匹配。

为了防止这种情况,我们可以说它必须后跟空格或文本的结尾:

(\d{10}(?:\s+\w+)+)
    (?=\s|$)      # it must be followed by a space or end of text
(?!\s*\d+\.\d+)

然而,这仍然存在问题。现在,它将匹配“... XMF”,但随后看到它后跟一个十进制数字和回溯。它将返回“... VBGF”然后匹配,因为“VBGF”后面没有小数。

为了防止这种情况,我们可以告诉正则表达式,它一旦匹配我们的主要部分就无法回溯:

(?> # added '?>': not allowed to backtrack once this group is matched
    \d{10}(?:\s+\w+)+)      
(?=\s|$)(?!\s*\d+\.\d+)

或者,如果您知道 sometext 中总会有2个部分,这也将解决回溯问题:

 (\d{10}(?:\s+\w+){2}  # can only occur twice
     )    
 (?=\s|$)(?!\s*\d+\.\d+)