正则表达式在多行上太贪心了

时间:2013-10-23 20:10:00

标签: php regex

我有以下代码:

$text = "Lorem ipsum dolor sit amet, [b]consectetur adipiscing elit[/b]. 
Nunc lorem velit, lacinia ut commodo in, suscipit vitae magna. 
Nam imperdiet neque blandit semper tempus. 
Curabitur sapien ante, vestibulum vitae ante a, condimentum dignissim tortor. Aenean adipiscing tincidunt lorem, non eleifend tellus suscipit a. Nulla convallis [b]
pulvinar ligula[/b], at tempor ante. Fusce a tellus enim. Vivamus nibh eros, ultrices at auctor quis, fringilla nec dolor. Aenean nec tincidunt odio, id pulvinar felis. Pellentesque in augue volutpat, gravida nibh eu, lobortis augue.";

preg_match_all("#(\[b\].*\[/b\])#s", $text, $value);

我的$value从第一个[b]返回到最后一个[/ b]。我需要它来单独匹配每一对。

据我了解,我必须使用最后的s来选择多行,但*过于贪心。我不能只使用?,因为我可以改变角色的数量......我缺少什么?

2 个答案:

答案 0 :(得分:2)

这是一个常见的错误。除非你做一些事情来避免它,否则正则表达式引擎会找到你的模式可能匹配的最长子字符串。根据上下文,可能有各种可能的解决方案,但对于支持Perl正则表达式语法的引擎,最简单的方法通常是使用您正在使用的重复运算符的“非贪婪”变体。也就是说,*?代替*+?代替+??代替?{m,n}?代替{ {1}}。

因此,在您的示例中,模式应显示为:

{m,n}

答案 1 :(得分:1)

避免延迟量词的另一种方法:

preg_match_all('~\[b](?>[^[]++|\[(?!/b]))*+\[/b]~', $text, $value);

通过这种方式,您可以避免两个问题:

  1. 贪婪量词不是问题,因为字符类停在每个开口方括号
  2. 因为你不使用点,所以你不关心's'修饰符和换行符。