如何在Python中使用re.sub()正确迭代

时间:2013-05-26 17:09:05

标签: python regex

我想制作一个创建脚注的Python脚本。我们的想法是查找排序"Some body text.{^}{Some footnote text.}"的所有字符串,并将其替换为"Some body text.^#",其中"^#"是正确的脚注编号。 (我的脚本的另一部分涉及实际打印文件底部的脚注。)我正在使用的当前代码是:

pattern = r"\{\^\}\{(.*?)\}"
i = 0
def create_footnote_numbers(match):
   global i
   i += 1
   return "<sup>"+str(i)+"</sup>"

new_body_text = re.sub(pattern, create_footnote_numbers, text)

这很好用,但是在i函数之外声明一个变量(create_footnote_numbers)然后必须在该函数内调用它似乎很奇怪。我原以为re里面会有一些东西会返回匹配的数字。

3 个答案:

答案 0 :(得分:12)

可以使用任何可调用对象,因此您可以使用类来跟踪编号:

class FootnoteNumbers(object):
    def __init__(self, start=1):
        self.count = start - 1

    def __call__(self, match):
        self.count += 1
        return "<sup>{}</sup>".format(self.count)


new_body_text = re.sub(pattern, FootnoteNumbers(), text)

现在,FootnoteNumbers()实例中包含了计数器状态,并且每次开始self.count运行时都会重新设置re.sub()

答案 1 :(得分:6)

这似乎非常适合a closure

def make_footnote_counter(start=1):
    count = [start - 1] # emulate nonlocal keyword
    def footnote_counter(match):
        count[0] += 1
        return "<sup>%d</sup>" % count[0]
    return footnote_counter

new_body_text = re.sub(pattern, make_footnote_counter(), text)

答案 2 :(得分:4)

变体和仅限Python-3的解决方案:

def make_create_footnote_numbers(start=1):
    count = start - 1
    def create_footnote_numbers(match):
        nonlocal count
        count += 1
        return "<sup>{}</sup>".format(count)
    return create_footnote_numbers

new_body_text = re.sub(pattern, make_create_footnote_numbers(), text)