在捕获组之前正则表达式懒惰

时间:2014-06-05 14:34:24

标签: regex lazy-evaluation

使用以下正则表达式

<w:p.*?\$\{test\}.*?\/w:p>

我试图匹配第一个

<w:p>
在&#34; $ {test}&#34;之前

和第一个

</w:p>

后。后工作得很好,使用?量词,但它拒绝在第一个停止

<w:body><w:p w:rsidRDefault="00271ADB"/><w:p w:rsidR="00C15291"><w:pPr><w:p w:rsidR="0093632F" w:rsidRDefault="0093632F"><w:pPr><w:rPr></w:rPr></w:pPr><w:r><w:rPr></w:rPr><w:br/><w:t>${test}</w:t></w:r></w:p></w:body>

这就是我所期望的结果:

<w:p w:rsidR="0093632F" w:rsidRDefault="0093632F"><w:pPr><w:rPr></w:rPr></w:pPr><w:r><w:rPr></w:rPr><w:br/><w:t>${test}</w:t></w:r></w:p>

但是这是返回的内容

<w:p w:rsidRDefault="00271ADB"/><w:p w:rsidR="00C15291"><w:pPr><w:p w:rsidR="0093632F" w:rsidRDefault="0093632F"><w:pPr><w:rPr></w:rPr></w:pPr><w:r><w:rPr></w:rPr><w:br/><w:t>${test}</w:t></w:r></w:p>

这是编辑器中的结果:http://i.imgur.com/HKSYdY8.png

这是我期待的结果:http://i.imgur.com/8HmThRb.png

1 个答案:

答案 0 :(得分:3)

您必须将第一个.*?更改为具有否定前瞻的重复组。您还应该注意到我在\s之后添加了<w:p,因此<w:pPr无法匹配。如果您有一些<w:p>个实例,则可能需要将其更改为<w:p(?:\s|>)

<w:p\s(?:(?!<w:p\s).)*?\$\{test\}.*?\/w:p>

Demo


RegEx从左到右匹配,因此没有真正的方法可以说&#34; lazy before&#34;。而不是.*?我使用了(?:(?!<w:p\s).)*?。让我们打破这个:

(?:         (?# begin non-capturing group for grouping/repetition)
  (?!       (?# begin negative lookahead)
    <w:p\s  (?# no <w:p ahead)
  )         (?# end negative lookahead)
  .         (?# match any character)
)*?         (?# lazy repetition)

这是如何工作的,一旦我们匹配<w:p\s,我们就进入非捕获/重复组。它执行零长度断言以确保<w:p\s在该点之前不存在,然后匹配一个字符。这懒惰地重复,直到我们点击${test}。如果表达式在前瞻中看到<w:p\s,它将失败......并且新匹配将开始备份,在开头匹配<w:p\s(并开始做更多的前瞻)。