python 替换多个单词保留大小写

python replace multiple words retaining case

我正在尝试在 Django 中编写一个过滤器,以根据搜索查询突出显示单词。例如,如果我的字符串包含 this is a sample string that I want to highlight using my filter 并且我的搜索存根是 samring,我想要的输出将是:

this is a <mark>sam</mark>ple st<mark>ring</mark> that I want to highlight using my filter

我正在使用 here 的答案来替换多个单词。我提供了以下代码:

import re

words = search_stubs.split()
rep = dict((re.escape(k), '<mark>%s</mark>'%(k)) for k in words)
pattern = re.compile('|'.join(rep.keys()))
text = pattern.sub(lambda m : rep[re.escape(m.group(0))], text_to_replace)

但是,当区分大小写时,这会中断。例如,如果我有字符串 Check highlight function,而我的搜索存根包含 check,这会中断。

在这种情况下所需的输出自然是:

<mark>Check</mark> highlight function

你不需要在这里找字典。 (?i) 称为不区分大小写的修饰符有助于进行不区分大小写的匹配。

>>> s = "this is a sample string that I want to highlight using my filter"
>>> l = ['sam', 'ring']
>>> re.sub('(?i)(' + '|'.join(map(re.escape, l)) + ')', r'<mark></mark>', s)
'this is a <mark>sam</mark>ple st<mark>ring</mark> that I want to highlight using my filter'

示例 2:

>>> s = 'Check highlight function'
>>> l = ['check']
>>> re.sub('(?i)(' + '|'.join(map(re.escape, l)) + ')', r'<mark></mark>', s)
'<mark>Check</mark> highlight function'

执行此操作的简单方法是不尝试构建字典将每个单词映射到其标记的等价物,而仅使用捕获组和对它。然后你可以只使用 IGNORECASE 标志进行不区分大小写的搜索。

pattern = re.compile('({})'.format('|'.join(map(re.escape, words))),
                     re.IGNORECASE)
text = pattern.sub(r'<mark></mark>', text_to_replace)

例如,如果 text_to_replace 是:

I am Sam. Sam I am. I will not eat green eggs and spam.

... 那么 text 将是:

I am <mark>Sam</mark>. <mark>Sam</mark> I am. I will not eat green eggs and spam

如果您真的确实想按照自己的方式去做,您可以。例如:

text = pattern.sub(lambda m: rep[re.escape(m.group(0))].replace(m, m.group(0)),
                   text_to_replace)

但这有点傻。您正在构建一个在值中嵌入 'sam' 的字典,这样您就可以将 'sam' 替换为您实际匹配的 'Sam'。


有关在替换中使用引用的详细信息,请参阅 Grouping in the Regular Expression HOWTO for more on groups and references, and the re.sub 文档。