Apa cara termudah untuk melakukan penggantian string case-insensitive dengan Python?
Apa cara termudah untuk melakukan penggantian string case-insensitive dengan Python?
Jawaban:
The string
tipe tidak mendukung ini. Anda mungkin lebih baik menggunakan sub metode ekspresi reguler dengan opsi 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'
, tetapi akan berguna jika nilai to-replace dimasukkan ke fungsi, jadi ini benar-benar lebih dari contoh yang baik daripada yang lainnya.
re.escape
, ada jebakan lain di sini yang gagal dihindari jawaban ini, yang dicatat di stackoverflow.com/a/15831118/1709587 : sejak re.sub
proses melarikan diri dari urutan, seperti dicatat dalam docs.python.org/library/re.html#re .sub , Anda harus melarikan diri semua backslash dalam string pengganti Anda atau menggunakan 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
hanya mendukung flag ini sejak Python 2.7.
Dalam satu baris:
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'
Atau, gunakan argumen "bendera" opsional:
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'
Melanjutkan jawaban bFloch, fungsi ini tidak akan berubah satu, tetapi semua kejadian lama dengan yang baru - dalam kasus yang tidak sensitif.
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
Seperti kata Blair Conrad string.replace tidak mendukung ini.
Gunakan regex re.sub
, tapi ingat untuk melarikan diri dari string pengganti terlebih dahulu. Perhatikan bahwa tidak ada opsi-flag di 2.6 untuk re.sub
, jadi Anda harus menggunakan pengubah tertanam'(?i)'
(atau objek-RE, lihat jawaban Blair Conrad). Juga, jebakan lain adalah bahwa sub akan memproses backslash lolos dalam teks pengganti, jika string diberikan. Untuk menghindari yang satu ini, Anda bisa memasukkan lambda.
Inilah fungsinya:
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'
Fungsi ini menggunakan fungsi str.replace()
dan re.findall()
. Ini akan menggantikan semua kejadian pattern
in string
dengan repl
cara case-insensitive.
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
Ini tidak memerlukan 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):]
Pengamatan menarik tentang detail dan opsi sintaks:
Python 3.7.2 (tag / v3.7.2: 9a3ffc0492, 23 Desember 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] di win32
import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)
'akar rumput akar rumput'
re.sub(r'treeroot', 'grassroot', old)
'TREEROOT akar rumput TREerOot'
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
'akar rumput akar rumput'
re.sub(r'treeroot', 'grassroot', old, re.I)
'TREEROOT akar rumput TREerOot'
Jadi awalan (? I) dalam ekspresi kecocokan atau menambahkan "flags = re.I" sebagai argumen keempat akan menghasilkan kecocokan case-insensitive. TETAPI, hanya menggunakan "re.I" sebagai argumen keempat tidak menghasilkan kecocokan case-sensitive.
Untuk perbandingan,
re.findall(r'treeroot', old, re.I)
['TREEROOT', 'treeroot', 'TREerOot']
re.findall(r'treeroot', old)
['akar pohon']
Saya sedang dikonversi ke urutan escape (gulir sedikit ke bawah), jadi saya mencatat bahwa re.sub mengkonversi karakter melarikan diri backslashed untuk melarikan diri dari urutan.
Untuk mencegahnya saya menulis yang berikut ini:
Ganti case sensitif.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Juga, jika Anda ingin mengganti dengan karakter escape, seperti jawaban lain di sini yang mendapatkan makna khusus karakter bashslash dikonversi untuk keluar dari urutan, cukup decode pencarian Anda dan, atau ganti string. Dalam Python 3, mungkin harus melakukan sesuatu seperti .decode ("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Diuji dalam Python 2.7.8
Semoga itu bisa membantu.
tidak pernah memposting jawaban sebelumnya dan utas ini benar-benar tua tetapi saya datang dengan solusi lain dan mengira saya bisa mendapatkan respons Anda, saya tidak berpengalaman dalam pemrograman Python jadi jika ada kelemahan yang muncul untuk itu, harap tunjukkan karena pembelajaran yang baik: )
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))