【问题标题】:PHP preg_replace() does not match white spaces and new lines: why?PHP preg_replace() 不匹配空格和新行:为什么?
【发布时间】:2016-08-25 11:40:50
【问题描述】:

我正在尝试编写一个从 HTML 中删除 cmets 的脚本,以 [! 开头的除外。例如,下面的 cmets 应该被移除:

<!-- one line comment -->

<!-- multiple line comment -->

删除以下内容:

&lt;!-- ! one line comment --&gt;

&lt;!--! one line comment --&gt;

<!--! multiple line comment -->

<!-- ! multiple line comment -->

<!-- !multiple line comment -->

&lt;!--[if lt IE 9]&gt;

我正在尝试运行以下命令:

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

但它不匹配第一类字符(任意数量的空格和换行符)。例如,&lt;!-- !test --&gt; 已从 HTML 中删除,而 &lt;!--!test --&gt; 则没有。

怎么了?

【问题讨论】:

  • 试试正则表达式
  • @sam, &lt;!--[^&gt;]*--&gt; 在这里帮不上忙。
  • 我完全同意@WiktorStribiżew 很抱歉

标签: php regex preg-replace pcre


【解决方案1】:

在你的模式中在&lt;!--[\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)

【讨论】:

  • 谢谢!那是一种魅力。你能简单解释一下为什么需要这个量词吗?
  • [\s\r\n]* 表示“匹配 [空格或回车或换行] 从 0 到无限次出现”。问题是正则表达式匹配了一些不应该匹配的 cmets,因为它没有找到空格,然后是空格,然后是 ! 。添加+ 会强制正则表达式匹配这些空格,然后向前看![,正如@WiktorStribiżew 在他的回答中解释的那样。
【解决方案2】:

关键是您需要检查! 后面是否有一些字符和换行符。

我建议

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

regex demo

详情

  • &lt;!-- - 文字 &lt;!--
  • \s*+ - 零个或多个空格,所有格匹配,以便后续的前瞻检查仅在匹配这些空格后执行
  • (?!!\N*\n) - 如果有 !,则否定前瞻失败匹配,然后在 ! 之后有 0+ 个字符而不是换行符,然后是换行符
  • .*? - 任何 0+ 个字符,尽可能少,直到第一个(注意:它可以替换为 [^-]*(?:-(?!-&gt;)[^-]*)* 以提高性能,demo
  • --&gt; - 文字 --&gt;
  • ~s - 一个 DOTALL 修饰符,. 匹配任何字符。

PHP 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);

【讨论】:

  • 我收到preg_match(): Compilation failed: PCRE does not support \L, \l, \N, \U, or \u at offset 13
  • 请检查您使用的内容并与我的演示进行比较。
  • 注意你也可以使用'~&lt;!--\s*+(?!!.*\n)[^-]*(?:-(?!-&gt;)[^-]*)*--&gt;~'
猜你喜欢
  • 1970-01-01
  • 2011-03-09
  • 2021-12-04
  • 1970-01-01
  • 2013-01-06
  • 2012-03-21
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多