【发布时间】:2015-08-16 01:34:01
【问题描述】:
你能解释一下这是如何工作的吗?这是一个例子:
<!-- 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 -->
首先,我尝试使用以下正则表达式来匹配条件 cmets 内的内容:
/<!--.*?stylesheet.*?-->/s
它失败了,因为正则表达式匹配第一个 <!-- 和最后一个 --> 之前的所有内容。然后我尝试使用另一种带有前瞻断言的模式:
/<!--(?=.*?stylesheet).*?-->/s
它可以工作并且完全符合我的需要。但是,以下正则表达式也可以:
/<!--(?=.*stylesheet).*?-->/s
最后一个正则表达式在前瞻断言中没有不情愿的量词。现在我很困惑。谁能解释一下它是如何工作的?也许这个例子有更好的解决方案?
更新:
我尝试在另一个文档中使用带有前瞻断言的正则表达式,但它无法匹配 cmets 之间的内容。所以,这个/<!--(?=.*?stylesheet).*?-->/s(以及这个/<!--(?=.*stylesheet).*?-->/s)是不正确的。不要使用它并尝试其他建议。
更新:
Jonny 5 找到了解决方案(请参阅答案)。他提出了三个选择:
- 使用否定的连字符来限制匹配。仅当标签之间没有连字符时,此选项才有效。如果样式表的 URL 为
/style-sheet.css,它将不起作用。 - 使用转义序列:
\K。它就像一个魅力。缺点如下:- 非常慢(在我的情况下,它比其他解决方案慢 8-10 倍)
- 仅自 PHP 5.2.4 起可用
- 使用前瞻来缩小匹配范围。这是我试图实现的目标,但我使用环视断言的经验不足以执行任务。
我认为以下是我的示例的一个很好的解决方案:
/(?s)<!--(?:(?!<!).)+?stylesheet.+?-->/
相同,但末尾带有 s 修饰符:
/<!--(?:(?!<!).)+?stylesheet.+?-->/s
正如我所说,这是一个很好的解决方案,但我设法改进了这种模式,并找到了另一种在我的情况下工作得更快的方法。
所以,最终的解决方案如下:
/<!--(?:(?!-->).)+?stylesheet.+?-->/s
感谢所有参与者提供有趣的答案。
【问题讨论】:
-
如果你想在 stylesheet 之前匹配
标签: php regex lookahead reluctant-quantifiers