Case insensitive replace
Case insensitive replace
What's the easiest way to do a case-insensitive string replacement in Python?
8 Answers
8
The string
type doesn't support this. You're probably best off using the regular expression sub method with the re.IGNORECASE option.
string
>>> import re
>>> insensitive_hippo = re.compile(re.escape('hippo'), re.IGNORECASE)
>>> insensitive_hippo.sub('giraffe', 'I want a hIPpo for my birthday')
'I want a giraffe for my birthday'
+1 for re.escape
– daboross
Dec 3 '13 at 7:30
Why re.escape for a string of letters only? Thanks.
– Elena
Nov 9 '14 at 18:34
@Elena, it's not needed for
'hippo'
, but would be useful if the to-replace value was passed into a function, so it's really more of a good example than anything else.– Blair Conrad
Nov 9 '14 at 23:19
'hippo'
Upvoted for
insensitive_hippo
. Also, for inline links to relevant documentation.– kungphu
Jan 29 '16 at 10:08
insensitive_hippo
import re
pattern = re.compile("hello", re.IGNORECASE)
pattern.sub("bye", "hello HeLLo HELLO")
# 'bye bye bye'
In a single line:
import re
re.sub("(?i)hello","bye", "hello HeLLo HELLO") #'bye bye bye'
re.sub("(?i)he.llo","bye", "he.llo He.LLo HE.LLO") #'bye bye bye'
Or, use the optional "flags" argument:
import re
re.sub("hello", "bye", "hello HeLLo HELLO", flags=re.I) #'bye bye bye'
re.sub("he.llo", "bye", "he.llo He.LLo HE.LLO", flags=re.I) #'bye bye bye'
Continuing on bFloch's answer, this function will change not one, but all occurrences of old with new - in a case insensitive fashion.
def ireplace(old, new, text):
idx = 0
while idx < len(text):
index_l = text.lower().find(old.lower(), idx)
if index_l == -1:
return text
text = text[:index_l] + new + text[index_l + len(old):]
idx = index_l + len(new)
return text
Very well done. Much better than regex; it handles all kinds of characters, whereas the regex is very fussy about anything non-alphanumeric. Preferred answer IMHO.
– fyngyrz
Jan 9 '17 at 19:01
All you have to do is escape the regex: the accepted answer is much shorter and easier to read than this.
– Mad Physicist
Oct 23 '17 at 19:45
This doesn't require RegularExp
def ireplace(old, new, text):
"""
Replace case insensitive
Raises ValueError if string not found
"""
index_l = text.lower().index(old.lower())
return text[:index_l] + new + text[index_l + len(old):]
Good one, however this does not change all occurrences of old with new, but only the first occurrence.
– rsmoorthy
Jan 23 '11 at 11:01
It's less readable than the regex version. No need to reinvent the wheel here.
– Johannes Bittner
Jan 30 '11 at 22:04
It would be interesting to do a performance comparison between this and the upvoted versions, it might be faster, which matters for some applications. Or it might be slower because it does more work in interpreted Python.
– D Coetzee
Nov 24 '11 at 0:59
Like Blair Conrad says string.replace doesn't support this.
Use the regex re.sub
, but remember to escape the replacement string first. Note that there's no flags-option in 2.6 for re.sub
, so you'll have to use the embedded modifier '(?i)'
(or a RE-object, see Blair Conrad's answer). Also, another pitfall is that sub will process backslash escapes in the replacement text, if a string is given. To avoid this one can instead pass in a lambda.
re.sub
re.sub
'(?i)'
Here's a function:
import re
def ireplace(old, repl, text):
return re.sub('(?i)'+re.escape(old), lambda m: repl, text)
>>> ireplace('hippo?', 'giraffe!?', 'You want a hiPPO?')
'You want a giraffe!?'
>>> ireplace(r'[binfolder]', r'C:Tempbin', r'[BinFolder]test.exe')
'C:Tempbintest.exe'
never posted an answer before and this thread is really old but i came up with another sollution and figured i could get your respons, Im not seasoned in Python programming so if there are appearant drawbacks to it, please point them out since its good learning :)
i='I want a hIPpo for my birthday'
key='hippo'
swp='giraffe'
o=(i.lower().split(key))
c=0
p=0
for w in o:
o[c]=i[p:p+len(w)]
p=p+len(key+w)
c+=1
print(swp.join(o))
For learning: generally when you do a search and replace on a string, it's better to not have to turn it into an array first. That's why the first answer is probably the best. While it's using an external module, it's treating the string as one whole string. It's also a bit clearer what's happening in the process.
– isaaclw
Apr 10 '12 at 14:43
I was having t being converted to the escape sequences (scroll a bit down), so I noted that re.sub converts backslashed escaped characters to escape sequences.
To prevent that I wrote the following:
Replace case insensitive.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Also, if you want it to replace with the escape characters, like the other answers here that are getting the special meaning bashslash characters converted to escape sequences, just decode your find and, or replace string. In Python 3, might have to do something like .decode("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Tested in Python 2.7.8
Hope that helps.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
If you're only doing a single replace, or want to save lines of code, it's more efficient to use a single substitution with re.sub and the (?i) flag: re.sub('(?i)' + re.escape('hippo'), 'giraffe', 'I want a hIPpo for my birthday')
– D Coetzee
Nov 24 '11 at 1:04