正则表达式删除条件注释

时间:2020-03-06 14:42:49  来源:igfitidea点击:

我想要一个正则表达式,可以匹配HTML源页面中的条件注释,因此我只能删除那些正则表达式。我想保留常规评论。

我也想避免使用。*?表示法(如果可能)。

文字是

foo

<!--[if IE]>

<style type="text/css">

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

</style>

<![endif]-->

bar

并且我想删除&lt;!-[如果IE]>&lt;![endif]->中的所有内容

编辑:这是因为BeautifulSoup我想删除这些标签。 BeautifulSoup无法解析,并提供了不完整的来源

EDIT2:[如果IE]不是唯一条件。还有很多,我没有所有可能组合的任何列表。

编辑3:Vinko Vrsalovic的解决方案有效,但是beautifulsoup失败的实际问题是由于条件注释中的流氓注释。喜欢

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

注意IE的<!-png修复->`注释吗?

尽管我的问题是解决,但我很乐意为此获得一个正则表达式解决方案。

解决方案

请勿为此使用正则表达式。我们会对包含开头标签的注释和不包含注释的注释感到困惑,并且做错了事。 HTML不是常规的,尝试使用单个常规表达式对其进行修改将失败。

为此使用HTML解析器。 BeautifulSoup是一种好,易用,灵活且坚固的工具,能够处理真实世界(意味着绝望的坏掉)的HTML。使用它,我们可以查找所有注释节点,检查其内容(如果需要,可以使用正则表达式),如果需要将其删除,则将其删除。

@Benoit

小校正(启用多行功能):

"<!--\[if IE\]>.*?<!\[endif\]-->"

这在没有行跨度选项的Visual Studio 2005中有效:

\ &lt;!-\ [如果是IE \] \> {。| \ n} * \ &lt;!\ [endif \]-\>

>>> 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>
>>>

带有bf4的python 3:

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(我对其进行了修改)

这是我们需要的:

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

它将过滤掉各种条件注释,包括:

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

<![if ! IE 6]>
    ...
<![endif]>
EDIT3: Vinko Vrsalovic's solution works, but the actual problem why beautifulsoup failed was because of a rogue  comment within the conditional comment. Like
  
  
     
     
  
  Notice the  comment?
  
  Though my problem was solve, I would love to get a regex solution for this.

这个怎么样:

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

在该正则表达式上执行替换,剩下\ 1 \ 4(或者$ 1 $ 4)作为替换。
我知道它有*。和。+?在其中,请参阅我对此信息的评论。

我只是选择:

import re

html = """fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs---><!--[if lt IE 7.]>\
<script defer type="text/javascript" src="pngfix_253168.js"></script><!--png fix for IE-->\
<![endif]-->fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->"""

# here the black magic occurs (whithout '.')
clean_html = ''.join(re.split(r'<!--\[[^¤]+?endif]-->', html))

print clean_html

'fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->'

N.B:[^]将匹配不是''的任何字符。这非常有用,因为它闪电般快,并且可以在任何键盘上找到此字符。但是诀窍在于,它真的很难键入(没有人会错误地键入它)并且没有人使用它:这是一种通用的货币设计char。

但是,如果我们不想使用,可以使用chr(7)生成" system bell"字符,该字符不可打印并且无法在网页中找到;

正如我所看到的,我们只需要担心下层隐藏的注释(以<!-开头的注释),并且不需要匹配单词if和后面的空格。这应该做我们想要的:

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

中间那堆烂摊子是为了满足我们不使用。*?的愿望,但我并不认为值得付出努力。如果我们使用设置了Re.S标志的正则表达式或者将其包装在(?s:...)中,则。*?方法应该可以正常工作。例如:

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