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

问题描述 投票:0回答:1

如何使用正则表达式(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]-->
html regex flex-lexer lex
1个回答
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>开始状态内,-只会匹配单个字符后退规则,如果它不能成为更长的-->匹配的一部分。

© www.soinside.com 2019 - 2024. All rights reserved.