用于删除条件注释的正则表达式

5 投票
7 回答
5124 浏览
提问于 2025-04-11 09:28

我想要一个正则表达式,可以匹配HTML源页面中的条件注释,这样我就可以只删除这些注释,而保留普通的注释。

如果可以的话,我也希望避免使用 .*? 这种写法。

文本是

foo

<!--[if IE]>

<style type="text/css">

ul.menu ul li{
    font-size: 10px;
    font-weight:normal;
    padding-top:0px;
}

</style>

<![endif]-->

bar

我想要删除所有在 <!--[if IE]><![endif]--> 之间的内容。

编辑:我想删除这些标签是因为使用了BeautifulSoup。BeautifulSoup无法解析这些内容,导致源代码不完整。

编辑2:[if IE]并不是唯一的条件。还有很多其他的条件,我也没有所有可能组合的列表。

编辑3:Vinko Vrsalovic的解决方案有效,但BeautifulSoup失败的真正原因是条件注释中有一个多余的注释。比如说:

<!--[if lt IE 7.]>
<script defer type="text/javascript" src="pngfix_253168.js"></script><!--png fix for IE-->
<![endif]-->

注意这个 <!--png fix for IE--> 注释吗?

虽然我的问题已经解决,但我还是希望能得到一个正则表达式的解决方案。

7 个回答

2

你需要准备这些:

<!(|--)\[[^\]]+\]>.+?<!\[endif\](|--)>

这个方法可以过滤掉各种条件注释,包括:

<!--[if anything]>
    ...
<[endif]-->

<![if ! IE 6]>
    ...
<![endif]>

编辑3: Vinko Vrsalovic 的解决方案有效,但实际上 beautifulsoup 失败的原因是因为条件注释中有一个多余的注释。就像这样:

注意到这个注释了吗?

虽然我的问题已经解决,但我还是希望能得到一个正则表达式的解决方案。

这样做怎么样:

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

对那个正则表达式进行替换,保留 \1\4(或者 $1$4)作为替换内容。
我知道里面有 .*? 和 .+?,可以看看我在这篇帖子上的评论。

2

在我看来,你只需要关注那些以 downlevel-hidden 开头的注释(也就是以 <!-- 开始的),而且你只需要匹配单词 if 和它后面的空格就可以了。这样做应该能满足你的需求:

"<!--\[if\s(?:[^<]+|<(?!!\[endif\]-->))*<!\[endif\]-->"

中间那一堆复杂的东西是为了满足你不想使用 .*? 的要求,但我觉得这样做其实没必要。使用 .*? 的方法如果你把正则表达式编译时设置 Re.S 标志,或者用 (?s:...) 包裹起来,效果也很好。例如:

"(?s:<!--\[if\s.*?<!\[endif\]-->)"
5
>>> from BeautifulSoup import BeautifulSoup, Comment
>>> html = '<html><!--[if IE]> bloo blee<![endif]--></html>'
>>> soup = BeautifulSoup(html)
>>> comments = soup.findAll(text=lambda text:isinstance(text, Comment) 
               and text.find('if') != -1) #This is one line, of course
>>> [comment.extract() for comment in comments]
[u'[if IE]> bloo blee<![endif]']
>>> print soup.prettify()
<html>
</html>
>>>     

使用 Python 3 和 BeautifulSoup 4:

from bs4 import BeautifulSoup, Comment
html = '<html><!--[if IE]> bloo blee<![endif]--></html>'
soup = BeautifulSoup(html, "html.parser")
comments = soup.findAll(text=lambda text:isinstance(text, Comment) 
               and text.find('if') != -1) #This is one line, of course
[comment.extract() for comment in comments]
[u'[if IE]> bloo blee<![endif]']
print (soup.prettify())

如果你的数据让 BeautifulSoup 感到困惑,你可以在处理之前通过修复它,或者自定义解析器,当然还有其他解决办法。

编辑:根据你的评论,你只需要修改传给 findAll 的 lambda 函数就可以了(我已经修改过了)。

撰写回答