What's the best way to regex replace a string in python but keep its case?

Question:

I’m looking to replace instances of a string in python but keep their original case.

For example, say I was replacing the strings ‘eggs’ with ‘bananas’:

This recipe requires eggs. –> This recipe requires bananas.

Eggs are good for breakfast. –> Bananas are good for breakfast.

I'M YELLING ABOUT EGGS! –> I'M YELLING ABOUT BANANAS!

Right now, I do an re.compile and .sub but I can’t figure out a smart way without explicitly declaring the three variants each time. I’m replacing about 100+ words so I imagine there has to be a smarter, more pythonic way.

EDIT: THIS IS NOT A DUPLICATE OF A PREVIOUSLY ASKED QUESTION. –> Some differences: I’m replacing the word with an entirely different word, not wrapping it in tags. Also, I need to keep the case even if its all caps, etc.. Please do not mark as duplicate without fully reading the question.

Asked By: keithhackbarth

||

Answers:

The key insight here is that you can pass a function to re.sub to do all sorts of checks before determining the proper replacement for a given match. Also, use the re.I flag to get all the cases.

import re
def replace_keep_case(word, replacement, text):
    def func(match):
        g = match.group()
        if g.islower(): return replacement.lower()
        if g.istitle(): return replacement.title()
        if g.isupper(): return replacement.upper()
        return replacement      
    return re.sub(word, func, text, flags=re.I)
    # return re.compile(word, re.I).sub(func, text) # prior to Python 2.7

Example:

>>> text = "Eggs with eggs, bacon and spam are good for breakfast... EGGS!"
>>> replace_keep_case("eggs", "spam", text)
"Spam with spam, bacon and spam are good for breakfast... SPAM!"
Answered By: tobias_k
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.