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?
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
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
from string import maketrans
"Abc".translate(maketrans("abcABC", "defDEF"))
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With