2012-09-26 6 views
32

tengo una cadena en Python, dicen The quick @red fox jumps over the @lame brown dog.Python reemplazar patrón de encordado con la salida de la función

estoy tratando de reemplazar cada una de las palabras que comienzan con @ con la salida de una función que toma la palabra como una argumento.

def my_replace(match): 
    return match + str(match.index('e')) 

#Psuedo-code 

string = "The quick @red fox jumps over the @lame brown dog." 
string.replace('@%match', my_replace(match)) 

# Result 
"The quick @red2 fox jumps over the @lame4 brown dog." 

¿Hay alguna manera inteligente de hacerlo?

+1

lo que tienes es bueno. lo haces en una declaración – tuxuday

Respuesta

58

Puede pasar una función a re.sub. La función recibirá un objeto coincidente como argumento, use .group() para extraer la coincidencia como una cadena.

>>> def my_replace(match): 
...  match = match.group() 
...  return match + str(match.index('e')) 
... 
>>> re.sub(r'@\w+', my_replace, string) 
'The quick @red2 fox jumps over the @lame4 brown dog.' 
+1

Hermoso. No sabía que podría pasar una función a Re.sub, pero sentí que debería ser capaz de hacerlo. – nathancahill

1

Probar:

import re 

match = re.compile(r"@\w+") 
items = re.findall(string) 
for item in items: 
    string = string.replace(item, my_replace(item) 

Esto le permitirá reemplazar cualquier cosa que comienza con @ con lo que la salida de su función. No estaba muy claro si necesita ayuda con la función también. Avíseme si ese es el caso

+0

're.findall (patrón, cadena)' - por favor corregir –

+0

Esto es bastante útil ya que le permite reemplazar solo los elementos coincidentes en la cadena. – Dannid

0

uno corto con expresiones regulares y reducir:

>>> import re 
>>> pat = r'@\w+' 
>>> reduce(lambda s, m: s.replace(m, m + str(m.index('e'))), re.findall(pat, string), string) 
'The quick @red2 fox jumps over the @lame4 brown dog.' 
4

yo no era consciente de que podía pasar una función a un re.sub() tampoco. Riffing sobre la respuesta de @Janne Karila para resolver un problema que tuve, el enfoque también funciona para múltiples grupos de captura.

import re 

def my_replace(match): 
    match1 = match.group(1) 
    match2 = match.group(2) 
    match2 = match2.replace('@', '') 
    return u"{0:0.{1}f}".format(float(match1), int(match2)) 

string = 'The first number is [email protected], and the second number is [email protected]' 
result = re.sub(r'([0-9]+.[0-9]+)(@[0-9]+)', my_replace, string) 

print(result) 

de salida:

The first number is 14.2, and the second number is 50.6000.

Este sencillo ejemplo requiere que todos los grupos de captura estar presentes (no hay grupos opcionales).

Cuestiones relacionadas