Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

case sensitive string replacement in Python

I need to replace a string in case sensitive way. For example

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

What can I do this with Python?

like image 671
prosseek Avatar asked Jun 09 '10 19:06

prosseek


4 Answers

Expanding on Mark Byers' answer, Here's a solution which works for replacement text of any length.
The trick is to send a function to 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')

Result:

de De dE de DE
def Def dEf deF DEF
defg Defg dEfg deFg DEFG
like image 57
Aaron Avatar answered Oct 12 '22 21:10

Aaron


Here's a method using regular expressions. The key point is that when it finds a match it first modifies the replacement string to match the casing of the matched string. This works because re.sub can take a function as a replacement instead of just a string.

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)

Result:

def -> def
Def -> Def
dEf -> dEf
deF -> deF
like image 44
Mark Byers Avatar answered Oct 12 '22 19:10

Mark Byers


from string import maketrans

"Abc".translate(maketrans("abcABC", "defDEF"))
like image 38
wilhelmtell Avatar answered Oct 12 '22 21:10

wilhelmtell


Long time lurker, thought I'd post a suggestion here as some of these seem fairly convoluted.

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

It does assume both strings are the same length, however you could easily replace the lambda with a proper function and check for None on the first input.

like image 1
Andrew Avatar answered Oct 12 '22 21:10

Andrew