Qual è il modo più semplice per eseguire una sostituzione di stringa senza distinzione tra maiuscole e minuscole in Python?
Qual è il modo più semplice per eseguire una sostituzione di stringa senza distinzione tra maiuscole e minuscole in Python?
Risposte:
Il stringtipo non supporta questo. Probabilmente stai meglio usando il metodo secondario dell'espressione regolare con l' opzione 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', ma sarebbe utile se il valore da sostituire fosse passato a una funzione, quindi è davvero più un buon esempio che altro.
re.escapel'ago, c'è un'altra trappola qui che questa risposta non riesce a evitare, annotata in stackoverflow.com/a/15831118/1709587 : poiché i re.subprocessi sfuggono alle sequenze, come notato in docs.python.org/library/re.html#re .sub , devi sfuggire a tutte le barre rovesciate nella stringa di sostituzione o usare 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 supporta questo flag solo da Python 2.7.
In una sola riga:
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'
In alternativa, utilizzare l'argomento facoltativo "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 sulla risposta di bFloch, questa funzione cambierà non una, ma tutte le occorrenze di vecchio con nuovo - in un modo insensibile al caso.
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
Come dice Blair Conrad, string.replace non supporta questo.
Usa regex re.sub, ma ricorda prima di sfuggire alla stringa di sostituzione. Nota che non c'è l'opzione flags in 2.6 per re.sub, quindi dovrai usare il modificatore incorporato '(?i)'(o un oggetto RE, vedi la risposta di Blair Conrad). Inoltre, un altro inconveniente è che il sub elaborerà gli escape di barra rovesciata nel testo di sostituzione, se viene fornita una stringa. Per evitarlo si può invece passare un lambda.
Ecco una funzione:
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'
Questa funzione utilizza entrambe le funzioni str.replace()e re.findall(). Sostituirà tutte le occorrenze di patternin stringcon repluna distinzione tra maiuscole e minuscole.
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
Questo non richiede 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):]
Un'osservazione interessante sui dettagli e le opzioni della sintassi:
Python 3.7.2 (tag / v3.7.2: 9a3ffc0492, 23 dic 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] su win32
import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)
'grassroot grassroot grassroot'
re.sub(r'treeroot', 'grassroot', old)
"TREEROOT grassroot TREerOot"
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
'grassroot grassroot grassroot'
re.sub(r'treeroot', 'grassroot', old, re.I)
"TREEROOT grassroot TREerOot"
Quindi il prefisso (? I) nell'espressione di corrispondenza o l'aggiunta di "flags = re.I" come quarto argomento comporterà una corrispondenza senza distinzione tra maiuscole e minuscole. MA, usando solo "re.I" come quarto argomento non risulta una corrispondenza senza distinzione tra maiuscole e minuscole.
Per confronto,
re.findall(r'treeroot', old, re.I)
['TREEROOT', 'treeroot', 'TREerOot']
re.findall(r'treeroot', old)
[ 'Treeroot']
Stavo per essere convertito nelle sequenze di escape (scorrere un po 'verso il basso), quindi ho notato che re.sub converte i caratteri di escape con backslash in sequenze di escape.
Per evitare che ho scritto quanto segue:
Sostituire la distinzione tra maiuscole e minuscole.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Inoltre, se si desidera che venga sostituito con i caratteri di escape, come le altre risposte qui che ottengono il significato speciale di caratteri bashslash convertiti in sequenze di escape, basta decodificare la ricerca e, o sostituire la stringa. In Python 3, potrebbe essere necessario eseguire operazioni come .decode ("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Testato in Python 2.7.8
Spero che aiuti.
non ho mai pubblicato una risposta prima e questo thread è davvero vecchio ma ho avuto un altro sollution e ho pensato che potrei ottenere la tua risposta, non sono esperto nella programmazione di Python, quindi se ci sono degli svantaggi apparenti ad esso, per favore segnalali dal suo buon apprendimento: )
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))