如何删除所有条件 HTML 评论?

How to remove all conditional HTML comments?

如何使用正则表达式 (lex & yacc) 删除所有 HTML 条件注释?我想删除所有评论,只留下最后一个 HTML 标签。

我试过这个 Regex "<!"(.*?)--> 来获取条件注释,但它没有用,我正在寻找与这些条件注释匹配的 Regex。

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

下面是 HTML 代码:我正在尝试删除所有评论并仅保留最后一个 HTML 标签。

<!--[if lte IE 7]> 

    <html class="ie7 oldie" xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"> 

<![endif]-->


<!--[if IE 8]> 

    <html class="ie8 oldie" xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"> 

<![endif]-->


<!--[if gt IE 8]><!--> 
    <html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"> 
<!--<![endif]-->

这里有两个关于 (f)lex 正则表达式的重要事实。 (有关 Flex 模式的完整文档,请参阅 flex manual。该部分不是很长。)

  1. 在 (f)lex 中,. 通配符匹配除换行符 之外的任何内容 。换句话说,它相当于[^\n]。所以 "<!".* 只会匹配到行尾。您可以改用 (.|\n) 来解决这个问题,但请参阅下文。

  2. (F)lex 不提供非贪婪重复 (*?)。所有重复都延伸到最长的可能匹配。因此,(.*?)--> 将匹配到行中的最后一个 -->,而 (.|\n)*?--> 将匹配到文件中的最后一个 -->

可以编写一个正则表达式来执行您想要的操作,尽管它有点乱:

<!--([^-]|-[^-]|--+[^->])*--+>

应该可以,只要输入文本不以未终止的注释结尾。 (你的模式中的引号是不必要的,因为 none 引用的字符对 (f)lex 有任何特殊意义,但它们不会造成伤害。我把它们排除在外是因为我认为它们对 make 没有贡献模式不易读。)

重复序列匹配以下任何一个:

  • -以外的字符;或
  • A - 后跟另一个 - 以外的东西;或
  • 两个或更多 - 后跟 > 以外的内容。

重复中的最后一个备选方案可能需要一些解释。潜在的问题是避免像

这样的输入出现问题
<!-- Comment with two many dashes --->

如果我们只是将诱人的 --[^>] 写为第三个选择,---> 将不会被识别为终止模式,因为 --- 将匹配 --[^>] (破折号不是右尖括号)然后 > 将匹配 [^-],并且扫描将继续。添加 + 以匹配更长的破折号序列是不够的,因为与许多正则表达式引擎一样,(f)lex 正在寻找最长的整体匹配,而不是每组备选方案中的最长子匹配。所以我们需要写--+[^->],不能匹配---

如果不清楚——我知道为什么不清楚——您可以改用 start condition 来编写一组更简单的模式:

%x COMMENT
%%
"<!--"    { BEGIN(COMMENT); }
<COMMENT>{
   "-->"   { BEGIN(INITIAL); }
   [^-]+   ;
   .|\n    ;
}

第二条 <COMMENT> 规则实际上只是一个提高效率的技巧;它避免了对每个角色触发空操作。有了第二条规则,最后一条规则实际上只能匹配一个 -,所以它可以这样写。但是完整地编写它可以让您删除第二条规则并向自己证明没有它它也可以工作。

像这样匹配评论的关键是 (f)lex 总是选择最长的匹配,这在某些方面类似于非贪婪匹配的目标。在 <COMMENT> 开始条件内,如果 - 不能成为 --> 匹配的一部分,则 - 将仅匹配单个字符回退规则。