当前位置: 首页 > 知识库问答 >
问题:

Python Regex,如何用单个模式替换多个事件?

解柏
2023-03-14

我试图制作一个模糊的自动完成建议框,突出显示带有HTML标记的搜索字符

例如,如果用户输入“ldi”,其中一个建议是“莱昂纳多·迪卡普里奥”,则期望的结果是“莱昂纳多·迪卡普里奥”。每个字符的第一次出现将按外观顺序高亮显示。

我现在正在做的是:

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

现在我想用替换结果组中的每个出现

我目前所做的是在结果上循环,并使用内置的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时

有没有办法简化这个?也许这里的正则表达式是过度杀戮?


共有2个答案

濮阳浩穰
2023-03-14

这应该行得通:

for result in result_groups:
    output_string = re.sub(fr'(.*?(?!<b>))({result})((?!</b>).*)',
         r'\1<b>\2</b>\3',
         output_string,
         flags=re.IGNORECASE)

在每次迭代的第一次出现的结果(?*懒惰这一起做第一次出现的魔力)将被取代。

郜谦
2023-03-14

一种使用re的方法。拆分:

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, 1)
        
        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')

re.split的一个特殊性是捕获在默认情况下作为部分包含在结果中。此外,即使第一个捕获在字符串的开始处匹配,也会在它之前返回一个空部分,这意味着搜索到的字母总是在子字符串列表中的奇数索引处。

 类似资料:
  • 假设我有'abbc'字符串,我想替换: ab- 如果我尝试两次替换,结果不是我想要的: 那么我可以使用什么sed命令来替换下面的命令呢? 编辑:实际上文本可能有2个以上的模式,我不知道我需要多少替换。因为有人回答说,是一个流编辑器,它的替代品是贪婪的,我想我需要使用一些脚本语言来实现这一点。

  • 基于SO上的各种线程(例如。用模式替换if else语句)我知道我可以用< code>Command模式替换多个if\else语句。 我的情况有点不一样。 我有一系列,只有当前一个命令不成功时,我才需要执行每个。 例如,假设我需要从一个假设的网页中检索文本——我可以使用屏幕抓取直接从页面中抓取文本,也可以从API中获取文本。如果屏幕抓取不成功,我只想从API获取文本。换句话说,如果“scrap”命

  • 问题内容: 给定一个像这样的字符串: 什么样的jQuery或JavaScript魔术可以用来将空间限制为最多一个空间? 目标: 问题答案: 假设您还想覆盖标签,换行符等,只需替换为: 如果您真的只想覆盖空格(而不是制表符,换行符等),请这样做:

  • 我真的不喜欢这样链接命令。有没有另一种方法在一个做?

  • 问题内容: 我想,以取代所有和使用 但我不喜欢我的代码… 有没有比以下方法更有效的方法: ? toLowerCase()就在那里,因为我也希望它也小写… 问题答案: 编辑: 使用正则表达式,并且在字符类内部使用仅识别一个而不是任何字符。

  • 问题内容: 如何将值更改为和将值更改为? 当我使用和所有值都更改为最后一个数组值。例: 结果: 问题答案: 这应该为您工作: 输出: 检出此DEMO:http : //codepad.org/b0dB95X5