0

我正在创建一个 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>'

问题在于 regex.sub 匹配但仅返回第一个字符。我在最后一行捕获/使用 \1 的方式有问题吗?

4

4 回答 4

3

请注意,(?: ...)问题中的序列专门关闭捕获。请参阅re文档(大约 1/5 通页),其中(重点添加)说:

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

如上一个答案中所述,如果在目标文本中使用了转义,则可以使用'('+ tag_join + ')'或使用建议的版本。"|".join(re.escape(tag) for tag in tags)

于 2013-03-08T18:47:44.963 回答
2

您正在捕捉(.)只有一个角色的部分。

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

请注意,如果您的标签名称中可能包含字母数字字符以外的任何字符,您需要这样做:

tag_join = "|".join(re.escape(tag) for tag in tags)
于 2013-03-08T18:18:30.937 回答
2

简单地做

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

那是因为你写了一个非捕获组(?:....),然后你必须把这个令人不安的东西(?=(.))放在前面。

于 2013-03-08T18:41:33.263 回答
1

这应该这样做

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)
于 2013-03-08T18:47:25.960 回答