【问题标题】:Python RegEx: how to replace each match individuallyPython RegEx:如何单独替换每个匹配项
【发布时间】:2019-12-12 21:37:27
【问题描述】:

我有一个字符串s、一个模式p 和一个替换r,我需要获取字符串列表,其中只有一个与p 匹配已被替换为r

例子:

s = 'AbcAbAcc'
p = 'A'
r = '_'

// Output:
['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']

我尝试过使用re.finditer(p, s),但我不知道如何用r 替换每个匹配项。

【问题讨论】:

    标签: python regex replace


    【解决方案1】:

    您可以在找到所有匹配项后手动替换它们:

    [s[:m.start()] + r + s[m.end():] for m in re.finditer(p,s)]
    

    结果是:

    ['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']
    

    它是如何工作的?

    • re.finditer(p,s) 将找到所有匹配项(每个匹配项都是 re.Match 对象)
    • re.Match 对象具有返回匹配位置的 start()end() 方法
    • 您可以使用以下代码替换字符串开头和结尾之间的部分:s[:begin] + replacement + s[end:]

    【讨论】:

    • 建议使用m.start() 代替m.span()[0]m.end() 代替m.span()[1]
    • @RootTwo:当然。谢谢。我更新了答案。
    【解决方案2】:

    你不需要正则表达式,它很简单

    [s[:i]+r+s[i+1:] for i,c in enumerate(s) if c==p]
    

    完整代码:See it working here

    s = 'AbcAbAcc'
    p = 'A'
    r = '_'
    
    x = [s[:i]+r+s[i+1:] for i,c in enumerate(s) if c==p]
    print(x)
    

    输出:

    ['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']
    

    如前所述,这仅适用于一个字符,对于超过一个字符或需要正则表达式的任何内容,请使用 zvone's answer

    对于我的答案和 zvone 的答案之间的性能比较(以及不使用正则表达式的第三种方法),请参阅 here 或使用以下代码自行测试:

    import timeit,re
    
    s = 'AbcAbAcc'
    p = 'A'
    r = '_'
    
    def x1():
        return [s[:i]+r+s[i+1:] for i,c in enumerate(s) if c==p]
    
    def x2():
        return [s[:i]+r+s[i+1:] for i in range(len(s)) if s[i]==p]
    
    def x3():
        return [s[:m.start()] + r + s[m.end():] for m in re.finditer(p,s)]
    
    print(x1())
    print(timeit.timeit(x1, number=100000))
    print(x2())
    print(timeit.timeit(x2, number=100000))
    print(x3())
    print(timeit.timeit(x3, number=100000))
    

    【讨论】:

    • 只有当p 总是一个字符长时才这样,但我需要p 将是一个实际的模式。但是,我提供的示例可以完美运行!
    猜你喜欢
    • 2019-05-16
    • 2020-09-01
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多