正则表达式去除 HTML 注释

Posted

技术标签:

【中文标题】正则表达式去除 HTML 注释【英文标题】:RegExp to strip HTML comments 【发布时间】:2010-11-08 06:09:47 【问题描述】:

寻找匹配和替换的正则表达式序列(最好是 php,但没关系)来改变它(开始和结束只是需要保留的随机文本)。

在:

fkdshfks khh fdsfsk 
<!--g1-->
<div class='codetop'>CODE: AutoIt</div>
<div class='geshimain'>
    <!--eg1-->
    <div class="autoit" style="font-family:monospace;">
        <span class="kw3">msgbox</span>
    </div>
    <!--gc2-->
    <!--bXNnYm94-->
    <!--egc2-->
    <!--g2-->
</div>
<!--eg2-->
fdsfdskh

到这个OUT:

fkdshfks khh fdsfsk 
<div class='codetop'>CODE: AutoIt</div>
<div class='geshimain'>
    <div class="autoit" style="font-family:monospace;">
        <span class="kw3">msgbox</span>
    </div>
</div>
fdsfdskh

谢谢。

【问题讨论】:

【参考方案1】:

您只是想删除 cmets 吗?怎么样

s/<!--[^>]*-->//g

或稍好一些(由提问者本人建议):

<!--(.*?)-->

但是请记住,html 不是正则的,所以使用正则表达式来解析它会导致当有人向它抛出奇怪的边缘情况时,你会陷入一个痛苦的世界。

【讨论】:

不,我想让IN变成OUT,就是这样。 我没有看到除了 cmets 之外的任何差异。你要让我们猜吗? @James ***s,IN 和 OUT 之间的唯一区别是 IN 有 cmets 而 OUT 没有。那么除了剥离 cmets 你还想要什么? 当您的评论中有 > 时,这不起作用。更好的版本是 /(?=/ @EugenMihailescu 好吧,当你认真对待它时,在非常规语言上使用正则表达式无论如何都是一个错误。【参考方案2】:
preg_replace('/<!--(.*)-->/Uis', '', $html)

此 PHP 代码将从 $html 字符串中删除所有 html 注释标记。

【讨论】:

修饰符的详细信息:U 使它变得不贪婪,因此只进入第一个关闭评论。 i 使其不区分大小写(不知道为什么这里需要这样做) s 意味着在 cmets 中也允许换行。 +1 表示 Ungreedy 专门与正则表达式分开调用,使其更易于理解/阅读。 我们已经使用这个脚本好几年了,它运行良好。但是请考虑它忽略了字符串&lt;!--可以出现在javascript标签内并在那里有效的事实。示例:&lt;script&gt; //... &lt;!--&lt;/script&gt; &lt;script type="text/javascript" src="http://.."&gt;&lt;/script&gt; &lt;/head&gt; &lt;!-- body --&gt;【参考方案3】:

更好的版本是:

(?=<!--)([\s\S]*?)-->

它匹配像这样的 html cmets:

<!--
multi line html comment
-->

<!-- single line html comment -->

最重要的是什么它匹配这样的cmets(其他人显示的其他正则表达式不涵盖这种情况):

<!-- this is my blog: <mynixworld.inf> -->

注意

虽然从语法上看,下面的注释是一个 html 注释,但您的浏览器可能会以某种不同的方式解析它,因此它可能具有特殊含义。剥离此类字符串可能会破坏您的代码。

<!--[if !(IE 8) ]><!-->

【讨论】:

这里有一个很棒的正则表达式。但是,更改为以下内容可能更有用,以便可以完全删除注释。 (?=&lt;!--)([\s\S]*?--&gt;) 这是最好的一个 为什么不能只是(&lt;!--[\s\S]*?--&gt;) 老实说,我认为在此评论 @andy_roddman 中发布的解决方案应该被标记为唯一的解决方案。 @Fabriziosabato:安迪的解决方案是我建议的解决方案的逐字副本,差异非常小,根本没有改善结果。测试:regex101.com/r/lUYBNb/1【参考方案4】:

不要忘记考虑条件 cmets,因为

<!--(.*?)-->

将删除它们。试试这个:

<!--[^\[](.*?)-->

不过,这也会删除下层显示的条件 cmets。

编辑:

这不会删除下层显示或下层隐藏的 cmets。

<!--(?!<!)[^\[>].*?-->

【讨论】:

【参考方案5】:

啊,我做到了,

<!--(.*?)-->

【讨论】:

@Paul:实际上更好,因为 > 前面没有 -- 不会结束 HTML 注释。改变的重要一点是使用非贪婪或最短匹配。 哦,对了,我忘记了。*?是非贪婪的。问一个非常模糊的问题仍然有点俗气,当有人用剥离 cmets 的正则表达式回答时抱怨,然后发布你自己的“剥离评论”答案。 为什么要投反对票?这个问题写得不好,但这个答案似乎很好。 @cube:因为已经发布了一个等效的答案,但被提问者无缘无故拒绝了。 我给他投了赞成票,因为尽管他固执地拒绝解释他想要什么,也拒绝解释他不喜欢我的回答的什么地方,但当你明白这一点时,他的回答比我的好一点。【参考方案6】:

如果您的 cmets 包含换行符,请尝试以下操作:

/<!--(.|\n)*?-->/g

【讨论】:

这不是处理换行问题的好方法。在 PHP 中,您可以使用 s 修饰符来允许 . 匹配换行符。在 JavaScript 中没有s 模式,但首选的解决方法是将. 替换为[\S\s]。它比(.|\n) 高效得多。顺便说一句,OP 使用的是 PHP,它没有 g 修饰符。 preg_match_all 是表示全局(g修饰符)的方式 这必须删除,因为它是一种危险且非常消耗资源的模式。【参考方案7】:
<!--([\s\S]*?)-->

在 javascript 和 VBScript 中也可以用作“.”。不匹配所有语言的换行符

【讨论】:

【参考方案8】:

这是我的尝试:

<!--(?!<!)[^\[>][\s\S]*?-->

这也将删除多行 cmets,并且不会删除下层显示或下层隐藏的 cmets。

【讨论】:

【参考方案9】:

下一个:

/( )*<!--((.*)|[^<]*|[^!]*|[^-]*|[^>]*)-->\n*/g

可以使用测试字符串删除多行 cmets:

fkdshfks khh fdsfsk 
<!--g1-->
<div class='codetop'>CODE: AutoIt</div>
    <div class='geshimain'>
    <!--eg1-->
    <div class="autoit" style="font-family:monospace;">
        <span class="kw3">msgbox</span>
    </div>
    <!--gc2-->
    <!--bXNnYm94-->
    <!--egc2-->
    <!--g2-->
</div>
<!--eg2-->
fdsfdskh

<!-- --
> test
- -->

<!-- --
<- test <
>
- -->

<!--
test !<
- <!--
-->

<script type="text/javascript">//<![CDATA[
    var xxx = 'a';   
    //]]></script>

ok

【讨论】:

这帮助我清理了 Angular 添加的一堆 HTML cmets。太棒了?【参考方案10】:

这些代码也是删除 javascript 代码。 太糟糕了:|

这里的示例 javascript 代码将使用此代码删除:

<script type="text/javascript"><!--
    var xxx = 'a';
    //-->
    </script>

【讨论】:

但是...为什么要把 JS 包裹在 html 注释标签中? 非常、非常、非常、非常古老的浏览器不运行 javascript,而是将其打印在页面上。注释标签阻止脚本被打印。 你可以用这个/(?:[^&gt;]\s|^)&lt;!--(?!&lt;!)[^\[&gt;][\s\S]*?--&gt;/gjsfiddle.net/3vkrrt8e【参考方案11】:
function remove_html_comments($html) 
   $expr = '/<!--[\s\S]*?-->/';
   $func = 'rhc';
   $html = preg_replace_callback($expr, $func, $html);
   return $html;


function rhc($search) 
   list($l) = $search;
   if (mb_eregi("\[if",$l) || mb_eregi("\[endif",$l) )  
      return $l;
   

【讨论】:

【参考方案12】:
// Remove multiline comment
    $mlcomment = '/\/\*(?!-)[\x00-\xff]*?\*\//';
    $code = preg_replace ($mlcomment, "", $code);
// Remove single line comment
    $slcomment = '/[^:]\/\/.*/';
    $code = preg_replace ($slcomment, "", $code);
// Remove extra spaces
    $extra_space = '/\s+/';
    $code = preg_replace ($extra_space, " ", $code);
// Remove spaces that can be removed
    $removable_space = '/\s?([\\;\=\(\)\\\/\+\*-])\s?/';
    $code = preg_replace ('/\s?([\\;\=\(\)\/\+\*-])\s?/', "\\1", $code);

【讨论】:

【参考方案13】:

如果你只想要文本或带有特定标签的文本,你可以用 PHP strip_tags 处理它,它还会删除 HTML 注释,你可以像这样保存你需要的 HTML 标签:

$text = '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>';
echo strip_tags($text, ['p', 'a']);

输出将是:

&lt;p&gt;Test paragraph.&lt;/p&gt; &lt;a href="#fragment"&gt;Other text&lt;/a&gt;

希望对大家有所帮助!

【讨论】:

以上是关于正则表达式去除 HTML 注释的主要内容,如果未能解决你的问题,请参考以下文章

Java:使用正则表达式从块注释中去除斜线和星号

用正则表达式批量删除注释(//abc和/*abc*/)

从补丁文件中去除 C 注释的方法

正则表达式去除 HTML 标签

正则表达式从 C# 中删除行注释

iOS 正则表达式去除特殊符号