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 string
tipo 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.escape
l'ago, c'è un'altra trappola qui che questa risposta non riesce a evitare, annotata in stackoverflow.com/a/15831118/1709587 : poiché i re.sub
processi 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 pattern
in string
con repl
una 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))