Python中区分大小写的字符串替换

11

我需要以区分大小写的方式替换字符串。例如:

abc -> def
Abc -> Def
aBc -> dEf
abC -> deF

在Python中如何实现这个功能?


@Mark:维基使用大小写字母来表示维基名称。我需要替换一些维基名称。 - prosseek
'wSg'的替代方案是什么? - joaquin
你所提出的问题的答案可能无法帮助你解决正在尝试解决的问题。如果前后长度不同怎么办? - Mark Byers
@Mark:实际上,我只是根据一小组规则替换字符串,而不是尝试替换所有可能的维基名称组合。因此,wilhelmtell的答案对我的目的非常有效。感谢您的回答。 - prosseek
7个回答

8
from string import maketrans

"Abc".translate(maketrans("abcABC", "defDEF"))

2
这假设输入字符串中没有相同的字符出现两次。 - Mark Byers
4
这种方法无法将“foo”替换为“bar”,因为“o”字符必须根据上下文映射到“a”或“r”中的一个。 - Tamás

7

在Mark Byers的回答基础上,这里提供一种适用于任意长度替换文本的解决方案。
关键是向re.sub()发送一个函数。

import re
def case_sensitive_replace(string, old, new):
    """ replace occurrences of old with new, within string
        replacements will match the case of the text it replaces
    """
    def repl(match):
        current = match.group()
        result = ''
        all_upper=True
        for i,c in enumerate(current):
            if i >= len(new):
                break
            if c.isupper():
                result += new[i].upper()
            else:
                result += new[i].lower()
                all_upper=False
        #append any remaining characters from new
        if all_upper:
            result += new[i+1:].upper()
        else:
            result += new[i+1:].lower()
        return result

    regex = re.compile(re.escape(old), re.I)
    return regex.sub(repl, string)

print case_sensitive_replace("abc Abc aBc abC ABC",'abc','de')
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','def')
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','defg')

结果:

de De dE de DE
def Def dEf deF DEF
defg Defg dEfg deFg DEFG

5

这里有一种使用正则表达式的方法。关键点在于当它找到匹配项时,首先修改替换字符串以匹配匹配字符串的大小写。这有效是因为re.sub可以将函数作为替换而不仅仅是一个字符串。

import re

def case_sensitive_replace(s, before, after):
    regex = re.compile(re.escape(before), re.I)
    return regex.sub(lambda x: ''.join(d.upper() if c.isupper() else d.lower()
                                       for c,d in zip(x.group(), after)), s)

test = '''
abc -> def
Abc -> Def
aBc -> dEf
abC -> deF
'''

result = case_sensitive_replace(a, 'abc', 'def')
print(result)

结果:

def -> def
Def -> Def
dEf -> dEf
deF -> deF

不起作用:case_sensitive_replace(“aman”,“aman”,“a man”)打印“a ma” - jbrown

1

我是一个长期潜水者,想在这里提出一个建议,因为其中一些似乎相当复杂。

print map(lambda a, b: b.lower() if a.islower() else b.upper(), "aBc", "def")

它假定两个字符串具有相同的长度,但是您可以轻松地用适当的函数替换 lambda 并检查第一个输入是否为 None。

0

这不是最有效的方法,而且非常粗糙,但可能像这样可以工作:

def case_insensitive_replace(string, old, new):
    upper_indices = [idx for idx, char in enumerate(string) if char.isupper()]
    replaced = list(string.lower().replace(old.lower(), new.lower()))
    for idx in upper_indices:
        replaced[idx] = replaced[idx].upper()
    return "".join(replaced)

0

我理解您想根据第一个字符串的大小写改变第二个字符串的情况,我提供以下解决方案。字符串s2会根据相应的字符串s1更改其大小写,并将结果存储在s3中。这里的一个假设是两个字符串具有相同的长度。

s1 = "AaBb"
s2 = "cdef"
s3 = ""
index = 0
length = len(s1)

while(True):
    if s1[index].isupper():
        temp = s2[index].upper()
    else:
        temp = s2[index].lower()
    s3 = s3 + temp
    index +=1
    if index == length:
        break
print s3

0

这个会起作用,不过你可能想要添加一些检查来确保字符串长度相同:

string1 = "AbcDEFghiJKLmnO"
string2 = "some other text"

string2 = "".join((string2[i].upper() if string1[i].isupper() else string2[i].lower() 
                   for i in range(len(string1))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接