RegExp练习:带有先行断言的不情愿量词

时间:2015-08-16 01:34:02

标签: php regex lookahead reluctant-quantifiers

你能解释一下这是如何运作的吗?这是一个例子:

<!-- The quick brown fox 
              jumps over the lazy dog -->

<!--[if IE 7]>
    <link rel="stylesheet" type="text/css" href="/supersheet.css" />
<![endif]-->

<!-- Pack my box with five dozen liquor jugs -->

首先,我尝试使用以下正则表达式来匹配条件注释中的内容:

/<!--.*?stylesheet.*?-->/s

失败,因为正则表达式匹配第一个<!--和最后一个-->之前的所有内容。然后我尝试使用另一种模式与前瞻断言:

/<!--(?=.*?stylesheet).*?-->/s

它完全符合我的需要。但是,以下正则表达式也起作用:

/<!--(?=.*stylesheet).*?-->/s

最后一个正则表达式在前瞻断言中没有一个不情愿的量词。现在我很困惑。谁能解释一下它是如何工作的?也许这个例子有更好的解决方案?

更新

我尝试在另一个文档中使用lookahead断言来使用正则表达式,并且它无法在注释之间添加内容。因此,这一个/<!--(?=.*?stylesheet).*?-->/s(以及此一个/<!--(?=.*stylesheet).*?-->/s)不正确。不要使用它并尝试其他建议。

更新

Jonny 5 找到了解决方案(参见答案)。他提出了三个选择:

  1. 使用否定连字符来限制匹配。仅当标记之间没有连字符时,此选项才有效。如果样式表的网址为/style-sheet.css,则无效。
  2. 使用转义序列:\K。它就像一个魅力。缺点如下:
    • 非常慢(在我的情况下,它比其他解决方案慢8到10倍)
    • 仅自PHP 5.2.4起可用
  3. 使用前瞻来缩小比赛范围。这是我试图实现的目标,但是我使用外观断言的经验不足以执行任务。
  4. 我认为以下是我的例子的一个很好的解决方案:

    /(?s)<!--(?:(?!<!).)+?stylesheet.+?-->/
    

    同样但最后使用s修饰符:

    /<!--(?:(?!<!).)+?stylesheet.+?-->/s
    

    正如我所说,这是一个很好的解决方案,但我设法改进了模式并找到了另一个在我的情况下工作得更快的模式。

    所以,最终解决方案如下:

    /<!--(?:(?!-->).)+?stylesheet.+?-->/s
    

    感谢所有与会者提供有趣的答案。

0 个答案:

没有答案