Який найпростіший спосіб здійснити заміну невразливих до регістру рядків у Python?
Який найпростіший спосіб здійснити заміну невразливих до регістру рядків у Python?
Відповіді:
string
Тип не підтримує це. Вам, мабуть, найкраще скористатися методом sub регулярного вираження з опцією 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'
, але було б корисно, якби значення для заміни було передано у функцію, тому це справді більше, ніж хороший приклад, ніж будь-що інше.
re.escape
вас є голка, тут є ще одна пастка, якої не можна уникнути цієї відповіді, зазначається в stackoverflow.com/a/15831118/1709587 : оскільки re.sub
обробляє послідовності втечі, як зазначено в docs.python.org/library/re.html#re .sub , вам потрібно відмовитися від усіх зворотних косих рядків у вашій заміні рядка або використовувати лямбда.
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
цей прапор підтримується лише з Python 2.7.
В одному рядку:
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'
Або скористайтеся необов'язковим аргументом "прапори":
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, ця функція змінить не одне, а всі випадки старого з новим - у випадку нечутливого.
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
Як каже Блер Конрад, string.replace це не підтримує.
Використовуйте регулярний вираз re.sub
, але не забудьте спочатку уникнути рядка заміни. Зауважте, що немає опцій прапорців в 2.6 для re.sub
, тому вам доведеться використовувати вбудований модифікатор'(?i)'
(або RE-об’єкт, див. Відповідь Блера Конрада). Крім того, ще одна помилка полягає в тому, що підданий буде обробляти ухили зворотної косої риски в тексті заміни, якщо задано рядок. Щоб цього уникнути, можна замість цього перейти в лямбда.
Ось функція:
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'
Ця функція використовує str.replace()
і re.findall()
функції, і функції. Він замінить всі входження pattern
в string
с repl
в регістронезавісімого чином.
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
Для цього не потрібно 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):]
Цікаве спостереження щодо деталей та варіантів синтаксису:
Python 3.7.2 (теги / v3.7.2: 9a3ffc0492, 23 грудня 2018, 23:09:28) [MSC v.1916 64 біт (AMD64)] у програмі win32
import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)
'низовий низовий низовий'
re.sub(r'treeroot', 'grassroot', old)
"TREEROOT низовий TREerOot"
re.sub(r'treeroot', 'grassroot', old, flags=re.I)
'низовий низовий низовий'
re.sub(r'treeroot', 'grassroot', old, re.I)
"TREEROOT низовий TREerOot"
Отже, префікс (? I) у виразі відповідності або додавання "flags = re.I" як четвертий аргумент призведе до невідповідності регістру. АЛЕ, використовуючи лише "re.I" як четвертий аргумент, це не призводить до невідповідності регістру.
Для порівняння
re.findall(r'treeroot', old, re.I)
['TREEROOT', 'treeroot', 'TREerOot']
re.findall(r'treeroot', old)
['корінь дерева']
У мене не було перетворено на послідовності евакуації (прокрутіть трохи вниз), тому я зазначив, що re.sub перетворює зворотні коси втекли символи для виходу з послідовностей.
Щоб запобігти цьому, я написав наступне:
Замініть корпус нечутливим.
import re
def ireplace(findtxt, replacetxt, data):
return replacetxt.join( re.compile(findtxt, flags=re.I).split(data) )
Крім того, якщо ви хочете, щоб його замінили символи втечі, як і інші відповіді тут, які набувають особливого значення символи bashslash, перетворені на схожі послідовності, просто розшифруйте свою знахідку або замініть рядок. У Python 3, можливо, доведеться зробити щось на зразок .decode ("unicode_escape") # python3
findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)
Випробувано на Python 2.7.8
Сподіваюся, що це допомагає.
ніколи раніше не публікував відповіді, і ця тема справді стара, але я придумав ще одне роздуття і подумав, що я можу отримати вашу відповідь. Я не досвідчений в програмуванні Python, тому, якщо є привабливі недоліки до цього, будь-ласка, вкажіть їх, оскільки його добре вивчають: )
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))