Python'da büyük / küçük harfe duyarlı olmayan bir dize değiştirme yapmanın en kolay yolu nedir?
Python'da büyük / küçük harfe duyarlı olmayan bir dize değiştirme yapmanın en kolay yolu nedir?
Yanıtlar:
string
Türü bu desteklemez. Muhtemelen re.IGNORECASE seçeneğiyle normal ifade alt yöntemini kullanarak en iyisi olursunuz .
>>> 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'
, ancak değiştirilecek değer bir işleve geçirilirse yararlı olacaktır, bu yüzden gerçekten her şeyden daha iyi bir örnektir.
re.escape
İğneye sahip olmanın yanı sıra , stackoverflow.com/a/15831118/1709587'de belirtildiği için bu cevabın kaçınamadığı başka bir tuzak var : çünkü docs.python.org/library/re.html#re'dere.sub
belirtildiği gibi işlemler dizilerden kaçıyor .sub , yedek dizenizdeki tüm ters eğik çizgilerden kaçmanız veya lambda kullanmanız gerekir.
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
Bu bayrağı yalnızca Python 2.7'den bu yana desteklediğini unutmayın .
Tek bir satırda:
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'
Veya isteğe bağlı "bayraklar" bağımsız değişkenini kullanın:
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'
BFloch'un cevabına devam ederek, bu işlev bir değil, eski olanların tüm yeni durumlarını değiştirir - bir durumda duyarsız bir şekilde.
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
Blair Conrad'ın dediği gibi string.replace bunu desteklemiyor.
Normal ifadeyi kullanın re.sub
, ancak önce yeni dizeden çıkmayı unutmayın. 2.6'da için bayrak seçeneği olmadığını unutmayın re.sub
, bu nedenle gömülü değiştiriciyi '(?i)'
(veya bir RE nesnesini kullanmanız gerekir, bkz. Blair Conrad'ın cevabı). Ayrıca, başka bir tuzak, bir dize verilirse alt öğenin değiştirilen metindeki ters eğik çizgi kaçışlarını işlemesidir. Bundan kaçınmak için bunun yerine bir lambda geçebilir.
İşte bir fonksiyon:
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'
Bu fonksiyon hem kullanır str.replace()
ve re.findall()
işlevleri. Bu tüm tekrarlarını yerini alacak pattern
içinde string
olan repl
bir harf duyarsız bir şekilde.
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
Bu RegularExp gerektirmez
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):]
Sözdizimi ayrıntıları ve seçenekleri hakkında ilginç bir gözlem:
Python 3.7.2 (etiketler / v3.7.2: 9a3ffc0492, 23 Aralık 2018, 23:09:28) win32'de [MSC v.1916 64 bit (AMD64)]
import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)
'tabandan tabandan tabandan'
re.sub(r'treeroot', 'grassroot', old)
'TREEROOT taban TREerOot'
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
'tabandan tabandan tabandan'
re.sub(r'treeroot', 'grassroot', old, re.I)
'TREEROOT taban TREerOot'
Dolayısıyla, eşleme ifadesindeki (? İ) öneki veya dördüncü argüman olarak "flags = re.I" eklenmesi büyük / küçük harfe duyarlı olmayan bir eşleşmeyle sonuçlanır. ANCAK, sadece "re.I" dördüncü argüman olarak kullanarak büyük / küçük harfe duyarlı olmayan bir eşleşme ile sonuçlanmaz.
Karşılaştırma için,
re.findall(r'treeroot', old, re.I)
['TREEROOT', 'ağaçkökü', 'TREerOot']
re.findall(r'treeroot', old)
['ağaç kökü']
Ben kaçış dizileri (biraz aşağı kaydırma) dönüştürülüyordu , bu yüzden re.sub kaçış dizileri kaçış geri kaçan karakter dönüştürür kaydetti .
Bunu önlemek için aşağıdakileri yazdım:
Büyük / küçük harfe duyarlı değildir.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Ayrıca, kaçış dizilerine dönüştürülen özel anlamı olan bashslash karakterlerini elde eden diğer cevaplar gibi, kaçış karakterleri ile değiştirilmesini istiyorsanız, bulmanızın kodunu çözmeniz veya dizeyi değiştirmeniz yeterlidir. Python 3'te .decode ("unicode_escape") # python3 gibi bir şey yapmanız gerekebilir.
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Python 2.7.8'de test edilmiştir
Umarım yardımcı olur.
daha önce hiç bir cevap yayınlanmadı ve bu konu gerçekten eski ama başka bir sollution ile geldi ve ben cevap alabilir düşündüm, Python programlama görmüş değilim, bu yüzden görünüşte dezavantajları varsa, iyi öğrenmesinden bu yana bunları işaret edin: )
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))