[英]Python Regex, how to substitute multiple occurrences with a single pattern?
我正在尝试制作一个模糊的自动完成建议框,突出显示带有 HTML 标签的搜索字符 <b></b>
例如,如果用户键入“ldi”并且其中一个建议是“Leonardo DiCaprio”,那么期望的结果是“ L eonar d o D i Caprio”。 每个字符的第一次出现按出现顺序突出显示。
我现在正在做的是:
def prototype_finding_chars_in_string():
test_string_list = ["Leonardo DiCaprio", "Brad Pitt","Claire Danes","Tobey Maguire"]
comp_string = "ldi" #chars to highlight
regex = ".*?" + ".*?".join([f"({x})" for x in comp_string]) + ".*?" #results in .*?(l).*?(d).*?(i).*
regex_compiled = re.compile(regex, re.IGNORECASE)
for x in test_string_list:
re_search_result = re.search(regex_compiled, x) # correctly filters the test list to include only entries that features the search chars in order
if re_search_result:
print(f"char combination {comp_string} are in {x} result group: {re_search_result.groups()}")
结果是
char combination ldi are in Leonardo DiCaprio result group: ('L', 'D', 'i')
现在我想用<b>[whatever in the result]</b>
替换结果组中的每个匹配项,但我不知道该怎么做。
我目前正在做的是循环结果并使用内置的str.replace
方法来替换出现的情况:
def replace_with_bold(result_groups, original_string):
output_string: str = original_string
for result in result_groups:
output_string = output_string.replace(result,f"<b>{result}</b>",1)
return output_string
这导致:
Highlighted string: <b>L</b>eonar<b>d</b>o D<b>i</b>Caprio
但是我认为当我已经有了匹配组时,像这样循环结果是浪费的。 此外,它甚至不正确,因为它从每个循环的开头检查字符串。 因此,对于输入 'ooo',结果如下:
char combination ooo are in Leonardo DiCaprio result group: ('o', 'o', 'o')
Highlighted string: Le<b><b><b>o</b></b></b>nardo DiCaprio
什么时候应该是Le<b>o</b>nard<b>o</b> DiCapri<b>o</b>
有没有办法简化这个? 也许这里的正则表达式有点矫枉过正?
这应该有效:
for result in result_groups:
output_string = re.sub(fr'(.*?(?!<b>))({result})((?!</b>).*)',
r'\1<b>\2</b>\3',
output_string,
flags=re.IGNORECASE)
在每次迭代中,第一次出现的结果( ?
使得.*
懒惰,这一起产生了第一次出现的魔力)如果在 ( (?!<b>)
<b>result</b>
和(?!</b>)
做那部分) 和\1 \2 \3
是第一组,第二组和第三组,另外我们将使用IGNORECASE
标志使其不区分大小写。
一种使用 re.split 的方法:
test_string_list = ["Leonardo DiCaprio", "Brad Pitt", "Claire Danes", "Tobey Maguire"]
def filter_and_highlight(strings, letters):
pat = re.compile( '(' + (')(.*?)('.join(letters)) + ')', re.I)
results = []
for s in strings:
parts = pat.split(s)
if len(parts) == 1: continue
res = ''
for i, p in enumerate(parts):
if i & 1:
p = '<b>' + p + '</b>'
res += p
results.append(res)
return results
filter_and_highlight(test_string_list, 'lir')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.