Jaki jest najłatwiejszy sposób na zastąpienie ciągu znaków bez uwzględniania wielkości liter w Pythonie?
Jaki jest najłatwiejszy sposób na zastąpienie ciągu znaków bez uwzględniania wielkości liter w Pythonie?
Odpowiedzi:
Ten string
typ tego nie obsługuje. Prawdopodobnie najlepiej będzie, jeśli użyjesz metody podrzędnej wyrażenia regularnego z opcją 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'
, ale byłoby przydatne, gdyby wartość do zastąpienia została przekazana do funkcji, więc jest to naprawdę dobry przykład niż cokolwiek innego.
re.escape
igły jest tu jeszcze jedna pułapka, której ta odpowiedź nie pozwala uniknąć, odnotowana na stackoverflow.com/a/15831118/1709587 : ponieważ re.sub
sekwencje ucieczki procesów, jak wspomniano w docs.python.org/library/re.html#re .sub , musisz albo usunąć wszystkie ukośniki odwrotne w twoim ciągu zastępującym, albo użyć 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
obsługuje tę flagę tylko od wersji Python 2.7.
W jednej linii:
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'
Lub użyj opcjonalnego argumentu „flagi”:
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'
Kontynuując odpowiedź bFlocha, funkcja ta zmieni nie jedno, ale wszystkie wystąpienia stare na nowe - w sposób niewrażliwy na wielkość liter.
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
Jak mówi Blair Conrad, string.replace tego nie obsługuje.
Użyj wyrażenia regularnego re.sub
, ale pamiętaj, aby najpierw uciec przed ciągiem zastępującym. Zauważ, że w 2.6 nie ma opcji flagi dla re.sub
, więc będziesz musiał użyć wbudowanego modyfikatora '(?i)'
(lub obiektu RE, zobacz odpowiedź Blaira Conrada). Kolejną pułapką jest to, że sub będzie przetwarzać znaki z ukośnikiem odwrotnym w tekście zastępującym, jeśli podany zostanie ciąg. Aby tego uniknąć, można zamiast tego podać lambdę.
Oto funkcja:
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'
Ta funkcja korzysta zarówno z funkcji, jak str.replace()
i re.findall()
. Będzie ona zastąpić wszystkich wystąpień pattern
w string
ze repl
w przypadku niewrażliwe sposób.
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
To nie wymaga 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):]
Interesująca obserwacja dotycząca szczegółów składni i opcji:
Python 3.7.2 (tags / v3.7.2: 9a3ffc0492, 23 grudnia 2018 r., 23:09:28) [MSC v.1916 64-bitowy (AMD64)] na win32
import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)
„oddolny oddolny”
re.sub(r'treeroot', 'grassroot', old)
„TREEROOT Grassroot TREerOot”
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
„oddolny oddolny”
re.sub(r'treeroot', 'grassroot', old, re.I)
„TREEROOT Grassroot TREerOot”
Tak więc prefiks (? I) w wyrażeniu dopasowującym lub dodanie „flags = re.I” jako czwartego argumentu spowoduje dopasowanie bez rozróżniania wielkości liter. ALE użycie samego „re.I” jako czwartego argumentu nie powoduje dopasowania bez rozróżniania wielkości liter.
Dla porownania,
re.findall(r'treeroot', old, re.I)
[„TREEROOT”, „treeroot”, „TREerOot”]
re.findall(r'treeroot', old)
['korzeń drzewa']
Miałem \ t być konwertowane na sekwencje specjalne (przewiń trochę w dół), więc zauważyłem, że funkcja re.sub konwertuje znaki ucieczki odwrócone ukośnikiem na sekwencje ucieczki.
Aby temu zapobiec, napisałem:
Zastąp bez rozróżniania wielkości liter.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Ponadto, jeśli chcesz, aby zastąpiono go znakami ucieczki, tak jak inne odpowiedzi tutaj, które otrzymują specjalne znaczenie znaków bashslash konwertowanych na sekwencje ucieczki, po prostu zdekoduj znalezione i lub zamień ciąg. W Pythonie 3 może być konieczne wykonanie czegoś takiego jak .decode ("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Przetestowano w Pythonie 2.7.8
Mam nadzieję, że to pomoże.
nigdy wcześniej nie publikowałem odpowiedzi, a ten wątek jest naprawdę stary, ale wymyśliłem inne rozwiązanie i pomyślałem, że mogę uzyskać twoją odpowiedź.Nie jestem doświadczony w programowaniu w Pythonie, więc jeśli są w nim widoczne wady, wskaż je, ponieważ dobrze się uczy: )
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))