Python 正则表达式标签

0 投票
3 回答
5683 浏览
提问于 2025-04-16 15:51

我想把这个字符串改成这样:

<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 个回答

2

这个问题的原因是,第一个分组是在 <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>
5

如果你选择不使用正则表达式,那就简单得多:

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

虽然我不太建议用正则表达式来解析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解析器

撰写回答