Python 正则表达式标签
我想把这个字符串改成这样:
<p><b> hello world </b></p>. 我在玩 <b> python </b>
改成:
<bold><bold>hello world </bold></bold>, 我在玩 <bold> python </bold>
我用了:
import re
pattern = re.compile(r'\<p>(.*?)\</p>|\<b>(.*?)\</b>')
print re.sub(pattern, r'<bold>\1</bold>', "<p><b>hello world</b></p>. I am playing <b> python</b>")
但是输出的结果不是我想要的,它报错说:未匹配的组
在这种情况下是可以工作的:
re.sub(pattern, r'<bold>\1</bold>', "<p>hello world</p>. I am playing <p> python</p>")
<bold> hello world </bold>
. 我在玩 <bold> python</bold>
3 个回答
这个问题的原因是,第一个分组是在 <p></p>
标签里面,而第二个分组是在 <b></b>
标签里面。不过,在你替换的时候,你却在引用第一个分组,而如果它匹配的是 <b></b>
,那就没有第一个分组了。我这里提供几个解决方案。
首先,
>>> pattern = re.compile(r'<(p|b)>(.*?)</\1>')
>>> print re.sub(pattern, r'<bold>\2</bold>',
"<p><b>hello world</b></p>. I am playing <b> python</b>")
<bold><b>hello world</b></bold>. I am playing <bold> python</bold>
这个代码可以匹配一对特定的标签。不过,正如你所看到的,它需要在字符串上使用两次,因为当它匹配到 <p></p>
标签时,会跳过里面的嵌套的 <b></b>
标签。
这是我推荐的选项:
>>> pattern = re.compile(r'<(/?)[pb]>')
>>> print re.sub(pattern, r'<\1bold>',
"<p><b>hello world</b></p>. I am playing <b> python</b>")
<bold><bold>hello world</bold></bold>. I am playing <bold> python</bold>
如果你选择不使用正则表达式,那就简单得多:
d = {'<p>':'<bold>','</p>':'</bold>','<b>':'<bold>','</b>':'</bold>'}
s = '<p><b> hello world </b></p>. I am playing <b> python </b>'
for k,v in d.items():
s = s.replace(k,v)
虽然我不太建议用正则表达式来解析HTML(几乎每种编程语言都有专门的库可以处理这个),但这个方法应该是可行的:
text = "<p><b> hello world </b></p>. I am playing <b> python </b>"
import re
pattern1 = re.compile(r'\<p>(.*?)\</p>')
pattern2 = re.compile(r'\<b>(.*?)\</b>')
replaced = re.sub(pattern1, r'<bold>\1</bold>', text)
replaced = re.sub(pattern2, r'<bold>\1</bold>', replaced)
我觉得你遇到的问题是因为Python处理分组的方式。试试下面的代码,你就明白我说的意思了:
text = "<p><b> hello world </b></p>. I am playing <b> python </b>"
import re
pattern = re.compile(r'\<p>(.*?)\</p>|\<b>(.*?)\</b>')
for match in pattern.finditer(text):
print match.groups()
你会看到以下结果:
('<b> hello world </b>', None) # Here captured the 1st group
(None, ' python ') # Here the 2nd ;)
另外,要注意的是,它首先匹配的是<p></p>
之间的内容,所以它把<b> hello world </b>
(你可能也想匹配的内容)当作第一个匹配项。也许调整一下pattern
中正则表达式的顺序可以解决这个问题,但也可能会出现相反的情况(比如<b><p> ... </p></b>
)。
我希望我能提供更多的信息,但我在用Python写正则表达式方面不是很在行。C#的处理方式和它不同。
补充:
我理解你可能想用正则表达式来学习或测试,不知道,但在实际的生产代码中,我会选择其他替代方案(就像@Senthil给你的建议)或者直接使用一个HTML解析器。