¿Cuál es la forma más fácil de hacer un reemplazo de cadena sin distinción entre mayúsculas y minúsculas en Python?
¿Cuál es la forma más fácil de hacer un reemplazo de cadena sin distinción entre mayúsculas y minúsculas en Python?
Respuestas:
El string
tipo no es compatible con esto. Probablemente sea mejor usar el submétodo de expresión regular con la opción re.IGNORECASE .
>>> 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'
'hippo'
, pero sería útil si el valor de reemplazo se pasara a una función, por lo que es más un buen ejemplo que cualquier otra cosa.
re.escape
usar su aguja, aquí hay otra trampa que esta respuesta no puede evitar, anotada en stackoverflow.com/a/15831118/1709587 : dado que re.sub
procesa secuencias de escape, como se indica en docs.python.org/library/re.html#re .sub , necesita escapar de todas las barras invertidas en su cadena de reemplazo o usar una lambda.
import re
pattern = re.compile("hello", re.IGNORECASE)
pattern.sub("bye", "hello HeLLo HELLO")
# 'bye bye bye'
re.sub('hello', 'bye', 'hello HeLLo HELLO', flags=re.IGNORECASE)
re.sub
solo admite esta bandera desde Python 2.7.
En una sola línea:
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'
O use el argumento opcional "flags":
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'
Continuando con la respuesta de bFloch, esta función cambiará no una, sino todas las ocurrencias de lo antiguo con lo nuevo, en un caso insensible.
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
Como Blair Conrad dice que string.replace no es compatible con esto.
Use la expresión regular re.sub
, pero recuerde escapar primero de la cadena de reemplazo. Tenga en cuenta que no hay opción de banderas en 2.6 para re.sub
, por lo que tendrá que usar el modificador incorporado '(?i)'
(o un objeto RE, consulte la respuesta de Blair Conrad). Además, otro escollo es que sub procesará los escapes de barra invertida en el texto de reemplazo, si se proporciona una cadena. Para evitar esto, uno puede pasar una lambda.
Aquí hay una función:
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:\Temp\bin', r'[BinFolder]\test.exe')
'C:\\Temp\\bin\\test.exe'
Esta función usa las funciones str.replace()
y re.findall()
. Se reemplazará todas las apariciones de pattern
en string
la repl
forma de mayúsculas y minúsculas.
def replace_all(pattern, repl, string) -> str:
occurences = re.findall(pattern, string, re.IGNORECASE)
for occurence in occurences:
string = string.replace(occurence, repl)
return string
Esto no requiere 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):]
Una observación interesante sobre los detalles y opciones de sintaxis:
Python 3.7.2 (etiquetas / v3.7.2: 9a3ffc0492, 23 de diciembre de 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] en win32
import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)
'la base la base la base'
re.sub(r'treeroot', 'grassroot', old)
'TREEROOT TREerOot de base'
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
'la base la base la base'
re.sub(r'treeroot', 'grassroot', old, re.I)
'TREEROOT TREerOot de base'
Entonces, el prefijo (? I) en la expresión de coincidencia o agregar "flags = re.I" como cuarto argumento dará como resultado una coincidencia que no distingue entre mayúsculas y minúsculas. PERO, usar solo "re.I" como el cuarto argumento no da como resultado una coincidencia entre mayúsculas y minúsculas.
Para comparacion,
re.findall(r'treeroot', old, re.I)
['TREEROOT', 'treeroot', 'TREerOot']
re.findall(r'treeroot', old)
['raíz del arbol']
Estaba teniendo \ t siendo convertido a las secuencias de escape (desplazarse un poco hacia abajo), así que noté que re.sub convierte los caracteres escapados con barra invertida en secuencias de escape.
Para evitar eso escribí lo siguiente:
Reemplazar mayúsculas y minúsculas.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Además, si desea reemplazarlo con los caracteres de escape, como las otras respuestas aquí que obtienen los caracteres de bashslash de significado especial convertidos en secuencias de escape, simplemente decodifique su búsqueda y / o reemplace la cadena. En Python 3, podría tener que hacer algo como .decode ("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Probado en Python 2.7.8
Espero que ayude.
nunca publiqué una respuesta antes y este hilo es muy antiguo, pero se me ocurrió otra solución y pensé que podría obtener su respuesta, no estoy experimentado en la programación de Python, así que si hay inconvenientes aparentes, indíquelos ya que es un buen aprendizaje: )
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))