PHP preg_replace()与空格和新行不匹配:为什么?

时间:2016-08-25 11:40:51

标签: php regex preg-replace pcre

我正在尝试编写一个从HTML中删除注释的脚本,但以[!开头的脚本除外。例如,应删除以下注释:

<!-- one line comment -->

<!-- multiple line comment -->

以下应删除:

<!-- ! one line comment -->

<!--! one line comment -->

<!--! multiple line comment -->

<!-- ! multiple line comment -->

<!-- !multiple line comment -->

<!--[if lt IE 9]>

我正在尝试运行以下内容:

$html = preg_replace('/<!--[\s\r\n]*[^![].*-->/Uis', '', $html);

但它与第一​​类字符(任意数量的空格和新行)不匹配。例如,<!-- !test -->已从HTML中删除,而<!--!test -->则不会。

怎么了?

2 个答案:

答案 0 :(得分:0)

重点是你需要检查!后面是否有一些字符和换行符。

我建议

'~<!--\s*+(?!!\N*\n).*?-->~s'

请参阅regex demo

<强>详情:

  • <!-- - 文字<!--
  • \s*+ - 零个或多个空格,占有率匹配,以便后续先行检查仅在匹配这些空格后执行
  • (?!!\N*\n) - 如果有!,那么负面预测会导致匹配失败,那么除了换行符之外的0 +字符以及!之后的换行符
  • .*? - 任意0个字符,尽可能少,直至第一个(注意:它可以替换为[^-]*(?:-(?!->)[^-]*)*以提升性能,{{3 }})
  • --> - 文字-->
  • ~s - DOTALL修饰符,.匹配任何字符。

demo

$re = '~<!--\s*+(?!!\N*\n).*?-->~s'; 
$str = "<!-- one line comment -->\n\n<!--\nmultiple line comment\n-->\n\nThe following should not be removed:\n\n<!-- ! one line comment -->\n\n<!--! one line comment -->\n\n<!--!\nmultiple line comment\n-->\n\n<!-- !\nmultiple line comment\n-->\n\n<!--\n!multiple line comment\n-->\n\n<!--[if lt IE 9]>"; 
preg_match_all($re, $str, $matches);
print_r($matches);

答案 1 :(得分:0)

在您的模式中+之后添加<!--[\s\r\n]*

$pattern = '<!--[\s\r\n]*+[^![].*-->';

$string = '<!-- one line comment -->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!--
multiple line comment
-->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!-- ! one line comment -->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!--! one line comment -->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!--!
multiple line comment
-->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!-- !
multiple line comment
-->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!--
!multiple line comment
-->';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

$string = '<!--[if lt IE 9]>';
var_dump(preg_replace('/' . $pattern . '/Uis', '', $string));

输出:

string '' (length=0)

string '' (length=0)

string '<!-- ! one line comment -->' (length=27)

string '<!--! one line comment -->' (length=26)

string '<!--!

multiple line comment

-->' (length=33)

string '<!-- !

multiple line comment

-->' (length=34)

string '<!--

!multiple line comment

-->' (length=33)

string '<!--[if lt IE 9]>' (length=17)