繁体   English   中英

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

[英]RegExp exercise: reluctant quantifier with a lookahead assertion

你能解释一下这是怎么回事吗? 这是一个例子:

<!-- 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 (以及这一个/ /<!--(?=.*?stylesheet).*?-->/s (? /<!--(?=.*stylesheet).*?-->/s )不正确。 不要使用它并尝试其他建议。

更新:

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

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

我认为以下是我的例子的一个很好的解决方案:

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

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

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

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

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

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

感谢所有参与者的有趣答案。

字符串stylesheet在测试文档中只提到一次,因此您尝试的两个正则表达式将以不同的方式匹配相同的内容。

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

这个做了以下几点:

  • 捕获<!--
  • 展望未来,捕捉角色,包括stylesheet 如果找不到则失败。
  • 捕获角色,包括-->
<!--(?=.*stylesheet).*?-->/s

这个做了以下几点:

  • 捕获<!--
  • 向前看,捕捉任何角色直到不再可能。 Backtrack,不断尝试匹配stylesheet 如果找不到则失败。
  • 捕获角色,包括-->

基本上,一个人需要显着地回溯,而另一个人则不需要。

如果您的主题是......

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

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

<!-- Pack my box with five dozen s -->

你得到两个不同的结果。 前者会找到第一个stylesheet ,而后者会找到第二个(和最后一个),因为它从字符串的末尾开始搜索。

要仅匹配<!-- ... stylesheet ... --> ,有很多方法:

1.)使用否定连字符[^-]来限制匹配并保持在<!--stylesheet

(?s)<!--[^-]+stylesheet.+?-->

[^-]仅允许不是连字符的字符。 请参阅regex101上的测试


2.)要获得“最后”或最接近的匹配而没有太多正则表达式的努力,也可以在ᗧ吃之前放一个贪婪的 如果不匹配全局/只匹配一个项目,则有意义。 使用\\ K在贪婪后重置

(?s)^.*\K<!--.+?stylesheet.+?-->

请参阅regex101上的测试 也可以使用捕获组并获取$ 1:( (?s)^.*(<!--.+?stylesheet.+?-->)


3.)使用前瞻来缩小范围通常更昂贵:

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

请参阅regex101上的测试 (?!<!). 展望<!--stylesheet中的每个角色,如果没有开始另一个<! ......留在一个元素里面 类似于否定的连字符解决方案。


而不是.*我使用.+ 一个或多个 - 取决于匹配什么。 这里+更合适。
使用什么解决方案取决于具体要求。 对于这种情况,我会使用第一个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM