Python regex在从列表编译时只替换第一个字符



我正在创建一个django过滤器,用于从列表中插入'a'标签到给定字符串中。

这是我目前为止写的:

def tag_me(text):
    tags = ['abc', 'def', ...]
    tag_join = "|".join(tags)
    regex = re.compile(r'(?=(.))(?:'+ tag_join + ')', flags=re.IGNORECASE)
    return regex.sub(r'<a href="/tag/1/">1</a>', text)

的例子:

tag_me('some text def')

的回报:

'some text <a href="/tag/d/">d</a>'
预期:

'some text <a href="/tag/def/">def</a>'

问题在于正则表达式。Sub匹配,但只返回第一个字符。我在最后一行捕捉/使用1的方式有问题吗?

注意,问题中的序列(?: ...)特别关闭捕获。参见re文档(大约1/5通过页面),其中(强调添加)说:

(?:...)正则括号的非捕获版本。匹配括号内的任何正则表达式,但是组匹配的子字符串在执行匹配后不能被检索或稍后在模式中引用。

如前所述,'('+ tag_join + ')'可以工作,如果在目标文本中使用转义,则使用建议的"|".join(re.escape(tag) for tag in tags)版本。

您正在捕获(.)部分,它只有一个字符。

我不确定我是否遵循您的正则表达式-简化版本r'('+ tag_join + ')'适用于您的示例。

请注意,如果标记名称中有可能包含字母数字以外的字符,则需要这样做:

tag_join = "|".join(re.escape(tag) for tag in tags)

只管做

import re
def tag_me(text):
    tags = ['abc', 'def']
    reg = re.compile("|".join(tags).join('()'),
                       flags=re.IGNORECASE)
    return reg.sub(r'<a href="/tag/1/">1</a>', text)
print '            %s' % tag_me('some text def')
print 'wanted:     some text <a href="/tag/def/">def</a>'

这是因为你写了一个非捕获组(?:....),然后你必须把这个干扰(?=(.))放在前面。

应该可以了

def tag_me(text):
    tags = ['abc', 'def', ]
    tag_join = "|".join(tags)
    pattern = r'('+tag_join+')'
    regex = re.compile(pattern, flags=re.IGNORECASE)
    return regex.sub(r'<a href="/tag/1/">1</a>', text)

最新更新