Python:如何在re.sub()的替换参数中添加计数器?
我想给HTML标签添加一些ID。比如,我想把:
<p>First paragraph</p>
<p>Second paragraph</p>
<p>Third paragraph</p>
改成
<p id="1">First paragraph</p>
<p id="2">Second paragraph</p>
<p id="3">Third paragraph</p>
我记得可以用一个叫做lambda的函数来实现这个功能,但我不太记得具体的写法了。
5 个回答
0
使用 re.sub()
方法
x=['<p>First paragraph</p>', '<p>Second paragraph</p>', '<p>Third paragraph</p>']
for i, p in enumerate(x,start=1):
... re.sub(r'^<p>', '<p id="%d">'%i, p)
...
'<p id="1">First paragraph</p>'
'<p id="2">Second paragraph</p>'
'<p id="3">Third paragraph</p>'
1
我想补充一下@Michael0x2a的回答。
他的代码里有一个大问题,特别是:如果没有任何东西被替换,计数器仍然会返回1。还有一些小问题。
为了绕过这个主要的问题,可以使用快速的哈希算法。我会用Adler32。
import re
import zlib
class Replace(object):
def __init__(self):
self.counter = 0
def __call__(self, match):
self.counter += 1
return '<p id="{0}">'.format(self.counter)
replace = Replace()
old = zlib.adler32(your_string)
replaced = re.sub(pattern, replace, your_string)
new = zlib.adler32(replaced)
if(old == new):
replace.counter = 0
2
这个方法可能不是特别通用,但应该能用。
def sub_p(string):
def inc(m, i=[0]):
i[0] += 1
return '<p id="%i">' % i[0]
return re.sub(r"<p>", inc, string)
5
如果你想使用正则表达式,一个简单粗暴的办法就是用一个全局变量,像这样:
i = 0
def replace(match):
global i
i += 1
return '<p id="{0}">'.format(i)
re.sub(pattern, replace, your_string)
另外,你也可以创建一个自定义的类,让它“假装”成一个函数,使用 __call__
方法,并把计数器定义为一个字段:
class Replace(object):
def __init__(self):
self.counter = 0
def __call__(self, match):
self.counter += 1
return '<p id="{0}">'.format(self.counter)
replace = Replace()
re.sub(pattern, replace, your_string)
7
我会使用一个HTML解析器,比如BeautifulSoup
。
这个想法是用enumerate()
来遍历所有段落,并给它们编号,从1
开始:
from bs4 import BeautifulSoup
data = """
<p>First paragraph</p>
<p>Second paragraph</p>
<p>Third paragraph</p>
"""
soup = BeautifulSoup(data, 'html.parser')
for index, p in enumerate(soup.find_all('p'), start=1):
p['id'] = index
print soup
输出结果:
<p id="1">First paragraph</p>
<p id="2">Second paragraph</p>
<p id="3">Third paragraph</p>