0

我尝试让所有文本到下一次出现的注释标记和注释标记中括号之间的文本。目前我只得到括号之间的评论标签文本,而不是下一条评论的内容,它只返回一个空字符串“”我有点困惑。谢谢!

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

过滤器.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) ""
  }
}
4

1 回答 1

1

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

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

键盘毒蛇演示


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

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

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

这正是通过这种前瞻模式表达的:

(?=<!--|$)

它读作“仅在后跟新注释或实际上是字符串结尾的位置匹配”。这就是它如何将这个懒惰.*?的子表达式鞭打成一个有用的动作——它不再能够在任何它想去的地方停下来。

于 2013-09-16T21:45:41.200 回答