Büyük / küçük harfe duyarlı olmayan değiştirme


Yanıtlar:


217

stringTü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'

11
Yalnızca tek bir değişiklik yapıyorsanız veya kod satırlarını kaydetmek istiyorsanız, re.sub ve (? İ) bayrağıyla tek bir ikame kullanmak daha verimlidir: re.sub ('(? İ)' + re .escape ('hippo'), 'zürafa', 'Doğum günüm için bir hIPpo istiyorum')
D Coetzee

3
Neden yalnızca bir harf dizisi için yeniden görünüm ? Teşekkürler.
Elena

8
@Elena, bunun için gerekli değildir '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.
Blair Conrad

2
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.
Mark Amery

84
import re
pattern = re.compile("hello", re.IGNORECASE)
pattern.sub("bye", "hello HeLLo HELLO")
# 'bye bye bye'

17
Veya bir astar: re.sub('hello', 'bye', 'hello HeLLo HELLO', flags=re.IGNORECASE)
Louis Yang

re.subBu bayrağı yalnızca Python 2.7'den bu yana desteklediğini unutmayın .
fuenfundachtzig

47

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'

14

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

Çok iyi yapılmış. Normal ifadeden çok daha iyi; regex alfasayısal olmayan herhangi bir şey hakkında çok telaşlı olsa da, her türlü karakteri ele alır. Tercih edilen cevap IMHO.
fyngyrz

Tek yapmanız gereken normal ifadeden kaçmak: kabul edilen cevap bundan daha kısa ve okunması daha kolay.
Deli Fizikçi

Escape sadece eşleştirme için çalışır, hedefteki ters eğik çizgiler hala işleri bozabilir.
ideasman42

4

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'

4

Bu fonksiyon hem kullanır str.replace()ve re.findall()işlevleri. Bu tüm tekrarlarını yerini alacak patterniçinde stringolan replbir 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

3

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):] 

3
İyi olan, ancak bu eski ile tüm tekrarlar değişmez, sadece ilk kez.
rsmoorthy

5
Normal ifade sürümünden daha az okunabilir. Burada tekerleği yeniden keşfetmeye gerek yok.
Johannes Bittner

Bu ve yükseltilmiş sürümler arasında bir performans karşılaştırması yapmak ilginç olacaktır, bazı uygulamalar için önemli olan daha hızlı olabilir. Veya daha yavaş olabilir, çünkü yorumlanmış Python'da daha fazla iş yapar.
D Coetzee

2

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ü']


Bu soruya bir cevap vermez. bu soruda zaten mevcut olan diğer yanıtlar üzerinde gelişmesini sağlamak için lütfen yanıtınızı düzenleyin .
hongsy

1

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.


0

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))

2
Öğrenmek için: genellikle bir arama yaptığınızda ve bir dizgiyi değiştirdiğinizde, önce onu bir diziye dönüştürmek gerekmez. Bu yüzden ilk cevap muhtemelen en iyisidir. Harici bir modül kullanırken, dizgiye bir bütün dizgi gibi davranır. Süreçte neler olduğu da biraz daha açık.
isaaclw

Öğrenmek için: bağlamı olmayan bir geliştiricinin bu kodu okumak ve ne yaptığını çözmek çok zor :)
Todd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.