Quel est le moyen le plus simple de remplacer une chaîne insensible à la casse en Python?
Quel est le moyen le plus simple de remplacer une chaîne insensible à la casse en Python?
Réponses:
Le string
type ne prend pas en charge cela. Il vaut probablement mieux utiliser la sous-méthode d' expression régulière avec l' option 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'
, mais serait utile si la valeur à remplacer était passée dans une fonction, donc c'est vraiment plus un bon exemple qu'autre chose.
re.escape
votre aiguille, il y a un autre piège ici que cette réponse ne parvient pas à éviter, noté dans stackoverflow.com/a/15831118/1709587 : puisque re.sub
traite les séquences d'échappement, comme indiqué dans docs.python.org/library/re.html#re .sub , vous devez soit échapper toutes les barres obliques inverses dans votre chaîne de remplacement, soit utiliser un 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
ne prend en charge cet indicateur que depuis Python 2.7.
En une seule ligne:
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'
Ou, utilisez l'argument optionnel "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'
Poursuivant sur la réponse de bFloch, cette fonction ne changera pas une, mais toutes les occurrences d'ancien avec nouveau - sans tenir compte de la casse.
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
Comme Blair Conrad dit que string.replace ne prend pas en charge cela.
Utilisez l'expression régulière re.sub
, mais n'oubliez pas d'échapper d'abord à la chaîne de remplacement. Notez qu'il n'y a pas d'option flags dans la version 2.6 pour re.sub
, vous devrez donc utiliser le modificateur intégré '(?i)'
(ou un objet RE, voir la réponse de Blair Conrad). De plus, un autre piège est que sub traitera les échappements de barre oblique inverse dans le texte de remplacement, si une chaîne est donnée. Pour éviter cela, on peut à la place passer dans un lambda.
Voici une fonction:
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'
Cette fonction utilise à la fois les fonctions str.replace()
et re.findall()
. Il remplacera toutes les occurrences de pattern
in string
par repl
d'une manière insensible à la casse.
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
Cela ne nécessite pas 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):]
Une observation intéressante sur les détails de la syntaxe et les options:
Python 3.7.2 (tags / v3.7.2: 9a3ffc0492, 23 décembre 2018, 23:09:28) [MSC v.1916 64 bits (AMD64)] sur 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 grassroot TREerOot'
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
`` à la base à la base à la base ''
re.sub(r'treeroot', 'grassroot', old, re.I)
'TREEROOT grassroot TREerOot'
Ainsi, le préfixe (? I) dans l'expression de correspondance ou l'ajout de "flags = re.I" comme quatrième argument entraînera une correspondance insensible à la casse. MAIS, utiliser simplement "re.I" comme quatrième argument ne donne pas de correspondance insensible à la casse.
En comparaison,
re.findall(r'treeroot', old, re.I)
['TREEROOT', 'treeroot', 'TREerOot']
re.findall(r'treeroot', old)
['racine d'arbre']
Je n'avais pas été converti en séquences d'échappement ( faites défiler un peu vers le bas), alors j'ai noté que re.sub convertit les caractères échappés antislashés en séquences d'échappement.
Pour éviter cela, j'ai écrit ce qui suit:
Remplacez insensible à la casse.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
De plus, si vous voulez qu'il soit remplacé par les caractères d'échappement, comme les autres réponses ici qui obtiennent les caractères bashslash de signification spéciale convertis en séquences d'échappement, décodez simplement votre recherche et, ou remplacez la chaîne. Dans Python 3, vous devrez peut-être faire quelque chose comme .decode ("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Testé en Python 2.7.8
J'espère que cela pourra aider.
Je n'ai jamais posté de réponse auparavant et ce fil est vraiment vieux mais j'ai trouvé une autre solution et j'ai pensé que je pourrais obtenir votre réponse, je ne suis pas expérimenté en programmation Python, donc s'il y a des inconvénients apparents, veuillez les signaler depuis son bon apprentissage: )
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))