如何删除所有条件HTML注释?

时间:2019-03-09 13:40:21

标签: html regex flex-lexer lex

如何使用正则表达式(lex和yacc)删除所有HTML条件注释?我想删除所有注释,仅保留最后一个HTML标记。

我已经尝试过此正则表达式"<!"(.*?)-->来获取条件注释,但是它不起作用,我正在寻找与这些条件注释匹配的正则表达式。

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

这是下面的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]-->

1 个答案:

答案 0 :(得分:0)

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

  1. 在(f)lex中,.通配符匹配除换行符之外的任何 。换句话说,它等效于[^\n]。因此"<!".*仅匹配到行尾。您可以改用(.|\n)来解决此问题,但请参见下文。

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

尽管有点杂乱,但可以编写一个满足您需要的正则表达式:

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

应该有效,只要输入文本不以未终止的注释结尾。 (您的模式中的引号是不必要的,因为没有引号的字符对(f)lex没有任何特殊含义,但是它们不会造成伤害。我将它们省略了,因为我认为它们不会使模式变得更难以理解)

重复的序列与以下任何一项匹配:

  • -以外的其他字符;或
  • 一个-后跟另一个-;或
  • 两个或多个-,后跟>以外的其他内容。

重复中的最后一种选择可能需要一些解释。潜在的问题是避免输入之类的问题

<!-- Comment with two many dashes --->

如果我们仅将诱人的--[^>]写为第三种选择,则--->将不会被视为终止模式,因为---将与--[^>]匹配(破折号不是直角括号),然后>将与[^-]匹配,并且扫描将继续。添加+来匹配更长的破折号是不够的,因为(f)lex像许多正则表达式引擎一样,正在寻找最长的整体匹配,而不是每组替代中最长的子匹配。因此,我们需要编写--+[^->],它不能匹配---

如果不清楚-我可以理解为什么不会-您可以改用start condition来编写一套简单得多的模式:

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

第二条<COMMENT>规则实际上只是一个效率漏洞;这样可以避免对每个角色触发不操作动作。有了第二条规则,最后一条规则实际上只能匹配单个-,因此可以这样写。但是完整编写它可以使您删除第二条规则,并向自己证明没有第二条规则即可。

按这样的方式匹配注释的关键见解是(f)lex总是选择最长的匹配,这在某种程度上类似于非贪婪匹配的目标。在<COMMENT>起始条件之内,-仅在不能成为更长的-->匹配项的一部分时,才匹配单字符回退规则。