我对正则表达式不是很熟悉,所以我正在寻找排除某些内容的语法。
我正在解析html代码中的<
、>
、"
和&
(以替换为<
等),并且我需要排除解析<br/>
。
例如:
<html><br/>
<head><title></title></head><br/>
<body><br/>
</body><br/>
</html>
我尝试了一些类似于
r'<\b?![br]'
等的方法,但它们并不完全有效。我使用re.sub()
进行替换。好的,现在问题再次开放,我可以将其作为答案来完成,所以......
除非我漏掉了什么,一旦只有<br/>
(没有任何变体),那么只需用<
替换<(?!br/>)
,并用>
替换(?<!<br/)>
,就可以了吗?
在Python中,看起来是这样的:
text = re.sub( '<(?!br/>)' , '<' , text )
text = re.sub( '(?<!<br/)>' , '>' , text )
(?!
...)
是一个负向先行断言——只有在其后面的文本不匹配其子表达式时,它才能成功匹配。(请注意,先行断言不会消耗其子表达式匹配的文本,它们只验证是否存在或不存在。)
类似地,(?<!
...)
是一个负向后行断言,使用前面的文本来做同样的事情。(?<!<br\s*/?)>
,那么它将不是Python的有效正则表达式,因为它代表着可变长度的匹配。(但是,您可以堆叠多个后行断言,因此如果有必要,您可以手动迭代各种选项。)re.sub('<(?!br/>)', '<', re.sub('(?<!<br/)>', '>', text))
。 - Peter Boughton这符合您的需求吗?:
import re
import htmlentitydefs
ss = '''
<html>
<br>
<title>"War & Peace"</title>
<body>Leon Tolstoy</body>
<br/>
</html>'''
print ss
print '\n\n'
uniquechars_repl = '"&'
conditional_repl = {'<':'<(?!br/>)',
'>':'(?<!<br/)>'}
all_repl = list(uniquechars_repl) + conditional_repl.keys()
di = dict( (b,'&%s;' % a) for a,b in htmlentitydefs.entitydefs.iteritems()
if b in all_repl)
pat = '|'.join(list(uniquechars_repl) + conditional_repl.values())
text = re.sub(pat , lambda mat: di[mat.group()], ss )
print text
结果
<html>
<br>
<title>"War & Peace"</title>
<body>Leon Tolstoy</body>
<br/>
</html>
<html>
<br>
<title>"War & Peace"</title>
<body>Leon Tolstoy</body>
<br/>
</html>
首先替换所有内容,然后在第二次替换中将"<br/>"替换为"<br/>"。
或者,为了通用化,您可以列出要“还原”的标签列表,并将"<tag>"替换为"<tag>","</tag>"替换为"</tag>","<tag/>"替换为"<tag/>"。
<br/>
(没有任何变体),那么只需用<
替换<(?!br/>)
,用>
替换(?<!<br/)>
,就可以了吗? - Peter Boughton