Мне нужно заменить строку чувствительным к регистру образом. Напримерсменная замена строки в Python
abc -> def Abc -> Def aBc -> dEf abC -> deF
Что я могу сделать с помощью Python?
Мне нужно заменить строку чувствительным к регистру образом. Напримерсменная замена строки в Python
abc -> def Abc -> Def aBc -> dEf abC -> deF
Что я могу сделать с помощью Python?
from string import maketrans
"Abc".translate(maketrans("abcABC", "defDEF"))
Это предполагает, что один и тот же символ не отображается дважды во входной строке. –
Это не будет работать для замены «foo» на «bar», поскольку символ «o» должен быть сопоставлен либо «a», либо «r» в зависимости от контекста. –
Возможно, модуль re
является тем, что вы ищете. В частности, функция re.sub
может использоваться для простого поиска/замены строк.
're.sub' не сохранит первоначальную заглавную строку. Если я правильно понимаю, оригинальный плакат хочет сохранить капитализацию. –
@Tam Ах, после того, как я снова прочитал вопрос, я думаю, что неправильно понял, о чем он просил.Если он ищет эффективную замену строки без учета регистра, за которой следует «сделать совпадение с предыдущей версией», тогда да, 're.sub' не будет правильным решением ... если не будет выполнена пользовательская функция как аргумент замены. Даже тогда, скорее всего, нет. – Rakis
Не самый эффективный способ, и это очень грубо, но, вероятно, что-то подобное может работать:
def case_insensitive_replace(string, old, new):
upper_indices = [idx for idx, char in enumerate(string) if char.isupper()]
replaced = list(string.lower().replace(old.lower(), new.lower()))
for idx in upper_indices:
replaced[idx] = replaced[idx].upper()
return "".join(replaced)
Вот метод с использованием регулярных выражений. Ключевым моментом является то, что когда он находит совпадение, он сначала модифицирует заменяющую строку, чтобы соответствовать оболочке согласованной строки. Это работает, потому что re.sub
может использовать функцию вместо замены.
import re
def case_sensitive_replace(s, before, after):
regex = re.compile(re.escape(before), re.I)
return regex.sub(lambda x: ''.join(d.upper() if c.isupper() else d.lower()
for c,d in zip(x.group(), after)), s)
test = '''
abc -> def
Abc -> Def
aBc -> dEf
abC -> deF
'''
result = case_sensitive_replace(a, 'abc', 'def')
print(result)
Результат:
def -> def Def -> Def dEf -> dEf deF -> deF
Я понимаю, что Вы хотите изменить вторую строку случая в соответствии с первой строки. Я прав? Итак, мое решение следующее. Строка s2 изменяет свой регистр в соответствии с соответствующей строкой s1. Результат сохраняется в s3. Одно из предположений здесь состоит в том, что две строки имеют одинаковую длину.
s1 = "AaBb"
s2 = "cdef"
s3 = ""
index = 0
length = len(s1)
while(True):
if s1[index].isupper():
temp = s2[index].upper()
else:
temp = s2[index].lower()
s3 = s3 + temp
index +=1
if index == length:
break
print s3
Долгосрочный люркер, подумал, что я разместил предложение здесь, поскольку некоторые из них кажутся довольно запутанными.
print map(lambda a, b: b.lower() if a.islower() else b.upper(), "aBc", "def")
Это делает предположим, обе строки имеют одинаковую длину, однако вы можете легко заменить лямбда с правильной функции и проверьте None на первом входе.
Это будет работать, хотя вы, вероятно, хотите, чтобы добавить некоторые проверки, что длины строк одинаковы:
string1 = "AbcDEFghiJKLmnO"
string2 = "some other text"
string2 = "".join((string2[i].upper() if string1[i].isupper() else string2[i].lower()
for i in range(len(string1))))
Расширяя ответ Марка Байерс, Вот решение, которое работает для замены текста любой длины.
Трюк заключается в том, чтобы отправить функцию re.sub().
import re
def case_sensitive_replace(string, old, new):
""" replace occurrences of old with new, within string
replacements will match the case of the text it replaces
"""
def repl(match):
current = match.group()
result = ''
all_upper=True
for i,c in enumerate(current):
if i >= len(new):
break
if c.isupper():
result += new[i].upper()
else:
result += new[i].lower()
all_upper=False
#append any remaining characters from new
if all_upper:
result += new[i+1:].upper()
else:
result += new[i+1:].lower()
return result
regex = re.compile(re.escape(old), re.I)
return regex.sub(repl, string)
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','de')
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','def')
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','defg')
Результат:
de De dE de DE
def Def dEf deF DEF
defg Defg dEfg deFg DEFG
@Mark: вики использует верхние/нижние символы для имени вики. Мне нужно заменить некоторые имена wiki. – prosseek
Что было бы заменой для 'wSg'? – joaquin
Возможно, ответ на заданный вами вопрос не поможет вам решить проблему, которую вы пытаетесь решить. Что делать, если до и после имеют разную длину? –