preg_match_all到下一个注释标签HTML包含。评论

时间:2013-09-16 21:43:21

标签: php regex comments preg-match expression

我尝试将所有文​​本添加到注释标记的下一个匹配项以及注释标记的括号之间的文本。 目前我只得到括号之间的注释标记文本而不是下一个注释的内容,它只返回一个空字符串“” 我有点困惑。谢谢!

header("Content-Type:text/plain");
$tmp= file_get_contents("filter.html");
preg_match_all('@<!--\[(.*?)\]-->(.*?)@su', $tmp, $found, PREG_SET_ORDER);
var_dump($found);

filter.html

<!--[%TEST%]-->
TEST
TEST
<!--[%DAS%]-->
DAS TEST
123456
<!--[%BKK%]-->
ABCDEFG
YXZ

我得到的输出是:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(15) "<!--[%TEST%]-->"
    [1]=>
    string(6) "%TEST%"
    [2]=>
    string(0) ""
  }
  [1]=>
  array(3) {
    [0]=>
    string(14) "<!--[%DAS%]-->"
    [1]=>
    string(5) "%DAS%"
    [2]=>
    string(0) ""
  }
  [2]=>
  array(3) {
    [0]=>
    string(14) "<!--[%BKK%]-->"
    [1]=>
    string(5) "%BKK%"
    [2]=>
    string(0) ""
  }
}

1 个答案:

答案 0 :(得分:1)

解决方案:将正则表达式更改为...

@<!--\[(.*?)\]-->(.*?)(?=<!--|$)@su

Codepad Viper Demo


说明:原始正则表达式几乎正确地使用了.*?表达式来获取所有非注释部分。我说'正确',因为这里确实需要懒惰修饰符(否则.*组合将很乐意消耗整个字符串)。我说'差不多',因为在这种特殊情况下修饰符太懒了 - 即使是空字符串也足以满足它(因为''匹配/.*/)。这就是为什么你在$found中得到那些空字符串的原因 - 懒惰的受害者被带到极端,他们是......

所以我们需要的是让正则表达式的这一部分更加“渴望” - 说服它继续吞噬字符串直到它......

  • 要么遇到新评论的开头('
  • 或到达字符串的末尾。

这就是这种前瞻模式所表达的:

(?=<!--|$)

它显示为'仅匹配在新注释之后的位置,或者实际上是字符串的结尾'。这就是它如何将这个懒惰的.*?子表达式转变成一个有用的运动 - 它不再能够在任何地方想要停止。