Python:如何在re.sub()的替换参数中添加计数器

时间:2014-10-31 15:58:48

标签: python html regex html-parsing auto-increment

我想将id添加到html标签。例如,我想改变:

<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>
IIRC,可以使用lambda函数来实现此功能,但我不记得确切的语法。

5 个答案:

答案 0 :(得分:6)

我会使用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>

答案 1 :(得分:3)

如果你想使用正则表达式,那么快速而肮脏的解决方案就是使用全局变量,如下所示:

i = 0

def replace(match):
    global i
    i += 1
    return '<p id="{0}">'.format(i)

re.sub(pattern, replace, your_string)

或者,您可以创建一个&#34;假装&#34;使用__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)

答案 2 :(得分: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)

答案 3 :(得分:1)

使用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>'

答案 4 :(得分: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