2010-06-09 31 views
6

Necesito reemplazar una cadena en mayúsculas y minúsculas. Por ejemplosustitución de cadena sensible a mayúsculas y minúsculas en Python

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

¿Qué puedo hacer con Python?

+0

@ Marcos: wiki utiliza caracteres en mayúsculas/minúsculas para el nombre wiki. Necesito reemplazar algunos nombres de wiki. – prosseek

+0

¿Cuál sería el reemplazo de 'wSg'? – joaquin

+0

Es posible que la respuesta a la pregunta que ha hecho no lo ayude con el problema que está tratando de resolver. ¿Qué pasa si el antes y el después tienen diferentes longitudes? –

Respuesta

7
from string import maketrans 

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

Esto supone que el mismo carácter no aparece dos veces en la cadena de entrada. –

+3

Esto no funcionará para reemplazar "foo" por "bar" ya que el carácter "o" debe asignarse a "a" o "r" según el contexto. –

0

El módulo re es probablemente lo que estás buscando. Específicamente, la función re.sub se puede usar para búsqueda/reemplazo de cadenas simples.

+0

're.sub' no mantendrá las mayúsculas originales de la cadena. Si entiendo correctamente, el póster original quiere conservar las mayúsculas. –

+0

@Tam Ah, después de leer la pregunta nuevamente, creo que entendí mal lo que estaba pidiendo.Si está buscando efectivamente un reemplazo de cadena insensible a mayúsculas y minúsculas seguido de un "hacer coincidir el caso con la versión anterior", entonces sí, 're.sub' no será la solución correcta ... a menos que se pase una función personalizada como el argumento de reemplazo. Incluso entonces, probablemente no. – Rakis

0
No

la manera más eficiente, y es muy crudo, pero probablemente algo como esto podría funcionar:

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

Aquí es un método que utiliza expresiones regulares. El punto clave es que cuando encuentra una coincidencia, primero modifica la cadena de reemplazo para que coincida con la carcasa de la cadena coincidente. Esto funciona porque re.sub puede tomar una función como reemplazo en lugar de solo una cadena.

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) 

Resultado:

 
def -> def 
Def -> Def 
dEf -> dEf 
deF -> deF 
0

entiendo que usted quiere cambiar el segundo caso cadena de acuerdo con la primera cadena. ¿Tengo razón? Entonces, mi solución es la siguiente. La cadena s2 cambia su caso de acuerdo con la cadena correspondiente s1. El resultado es almacenar en s3. Una suposición aquí es que las dos cadenas tienen la misma longitud.

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

Long time lurker, pensé en publicar una sugerencia aquí ya que algunos de estos parecen bastante intrincados.

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

lo hace asumen ambas cadenas son de la misma longitud, sin embargo, puede fácilmente reemplazar el lambda con una función adecuada y comprobar si hay ninguno en la primera entrada.

0

Esto funcionará, aunque es probable que desee añadir algunos cheques que las longitudes de cadena son los mismos:

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

Ampliando la respuesta de Mark Byers, he aquí una solución que funciona para el texto de reemplazo de cualquier longitud.
El truco es enviar una función al 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') 

Resultado:

de De dE de DE 
def Def dEf deF DEF 
defg Defg dEfg deFg DEFG 
Cuestiones relacionadas