Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

regex

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.

like image 694
keithhackbarth Avatar asked Jul 22 '14 17:07

keithhackbarth


1 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!
like image 78
tobias_k Avatar answered Oct 19 '22 08:10

tobias_k