2010-06-09 3 views
6

Мне нужно заменить строку чувствительным к регистру образом. Напримерсменная замена строки в Python

 
abc -> def 
Abc -> Def 
aBc -> dEf 
abC -> deF 

Что я могу сделать с помощью Python?

+0

@Mark: вики использует верхние/нижние символы для имени вики. Мне нужно заменить некоторые имена wiki. – prosseek

+0

Что было бы заменой для 'wSg'? – joaquin

+0

Возможно, ответ на заданный вами вопрос не поможет вам решить проблему, которую вы пытаетесь решить. Что делать, если до и после имеют разную длину? –

ответ

7
from string import maketrans 

"Abc".translate(maketrans("abcABC", "defDEF")) 
+2

Это предполагает, что один и тот же символ не отображается дважды во входной строке. –

+3

Это не будет работать для замены «foo» на «bar», поскольку символ «o» должен быть сопоставлен либо «a», либо «r» в зависимости от контекста. –

0

Возможно, модуль re является тем, что вы ищете. В частности, функция re.sub может использоваться для простого поиска/замены строк.

+0

're.sub' не сохранит первоначальную заглавную строку. Если я правильно понимаю, оригинальный плакат хочет сохранить капитализацию. –

+0

@Tam Ах, после того, как я снова прочитал вопрос, я думаю, что неправильно понял, о чем он просил.Если он ищет эффективную замену строки без учета регистра, за которой следует «сделать совпадение с предыдущей версией», тогда да, 're.sub' не будет правильным решением ... если не будет выполнена пользовательская функция как аргумент замены. Даже тогда, скорее всего, нет. – Rakis

0

Не самый эффективный способ, и это очень грубо, но, вероятно, что-то подобное может работать:

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

Вот метод с использованием регулярных выражений. Ключевым моментом является то, что когда он находит совпадение, он сначала модифицирует заменяющую строку, чтобы соответствовать оболочке согласованной строки. Это работает, потому что 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 
0

Я понимаю, что Вы хотите изменить вторую строку случая в соответствии с первой строки. Я прав? Итак, мое решение следующее. Строка 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 
1

Долгосрочный люркер, подумал, что я разместил предложение здесь, поскольку некоторые из них кажутся довольно запутанными.

print map(lambda a, b: b.lower() if a.islower() else b.upper(), "aBc", "def") 

Это делает предположим, обе строки имеют одинаковую длину, однако вы можете легко заменить лямбда с правильной функции и проверьте None на первом входе.

0

Это будет работать, хотя вы, вероятно, хотите, чтобы добавить некоторые проверки, что длины строк одинаковы:

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

Расширяя ответ Марка Байерс, Вот решение, которое работает для замены текста любой длины.
Трюк заключается в том, чтобы отправить функцию 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 
Смежные вопросы