2011-03-16 5 views
10

nuevo en python. Esto es probablemente simple, pero no he encontrado una respuesta.Cómo sub con grupos y variables coincidentes en Python

rndStr = "20101215" 
rndStr2 = "20101216" 
str = "Looking at dates between 20110316 and 20110317" 
outstr = re.sub("(.+)([0-9]{8})(.+)([0-9]{8})",r'\1'+rndStr+r'\2'+rndStr2,str) 

La salida que estoy buscando es:

Looking at dates between 20101215 and 20101216 

Pero en cambio me sale:

P101215101216 

Los valores de los dos rndStr de realidad no importa. Supongamos que es aleatorio o se toma de la entrada del usuario (puse vals estáticos aquí para mantenerlo simple). Gracias por cualquier ayuda.

Respuesta

21

Sus referencias son ambiguas. Su cadena de reemplazo se convierte en

\120101215\220101216 

que es más bien dos grandes números para ser backreferencing :)

Para solucionarlo, utilice esta sintaxis:

r'\g<1>'+rndStr+r'\g<2>'+rndStr2 

También tienen demasiados conjuntos de paréntesis (o "corchetes" si hablas inglés británico como yo :) - no necesitas paréntesis alrededor de las partes [0-9]{8} que no estás retrocediendo:

re.sub("(.+)[0-9]{8}(.+)[0-9]{8}",... 

debería ser suficiente.

(Y, como se menciona en otra parte, no use str como nombre de variable. A menos que desee pasar las edades depurando por qué str.replace() ya no funciona. No es que alguna vez lo haya hecho una vez ... noooo. :)

por lo que todo lo convierte en:

import re 
rndStr = "20101215" 
rndStr2 = "20101216" 
s = "Looking at dates between 20110316 and 20110317" 
outstr = re.sub("(.+)[0-9]{8}(.+)[0-9]{8}", r'\g<1>'+rndStr+r'\g<2>'+rndStr2, s) 
print outstr 

Producir:

Looking at dates between 20101215 and 20101216 
-1
rndStr = "20101215" 
rndStr2 = "20101216" 
mys = "Looking at dates between {0} and {1}".format(rndStr, rndStr2) 

Por favor, no use str como nombre de variable; sobrescribe el tipo incorporado str.

+1

No creo que OP pregunte por esto. –

+0

La cadena original tiene dos fechas (diferentes), por lo que no funcionará. Gracias de cualquier manera. –

3

Aviso si cambia el valor de rndStr o rndStr2 para enviar mensajes de texto (como 'abc') en lugar de dígitos, ¿obtiene algo más cercano al resultado esperado?

En su expresión a re.sub tiene r'\1'+rndStr+... Este combina en '\1'+'20101215' que luego intenta hacer referencia a la referencia posterior de \120101215 que probablemente no es lo que pretende ...

Usted puede utilizar el nombre de vuelta referencias para hacer la parte de atrás referencia inequívoca:

rep1 = "20101215" 
rep2 = "20101216" 
st = "Looking at dates between 20110316 and 20110317" 

print re.sub(r'(?P<fp>.+)[0-9]{8}(?P<lp>.+)[0-9]{8}', 
      r'\g<fp>'+rep1+r'\g<lp>'+rep2,st) 

Mejor aún, utilizar una sintaxis más fácil de entender y comprobar el retorno del intento de partido:

m=re.search(r'(?P<fp>.+)[0-9]{8}(?P<lp>.+)[0-9]{8}',st) 
if m: 
    print m.group('fp')+rep1+m.group('lp')+rep2 #you could use m.group(1) too 
else: 
    print "no match..." 

En ambos casos, se produce la cadena deseada de Looking at dates between 20101215 and 20101216 .

docs El pitón en referencias hacia atrás con nombre:

(?P<name>...)

Al igual que en paréntesis regulares, pero la subcadena encontrada por el grupo es accesible dentro del resto de la expresión regular a través de lo simbólico nombre del grupo 'nombre'. Los nombres de grupo deben ser identificadores de Python válidos, y cada nombre de grupo debe definirse solo una vez dentro de una expresión regular. Un grupo simbólico también es un grupo numerado , como si el grupo no tuviera el nombre . Por lo que el grupo denominado 'id' en el ejemplo a continuación también se puede hacer referencia como el grupo numerado 1.

Por ejemplo, si el patrón es (?P<id>[a-zA-Z_]\w*), el grupo puede ser referenciado por su nombre en argumentos a los métodos de objetos marcadores, tales como m.group('id') o m.end('id'), y también por su nombre en la expresión regular sí (utilizando (?P=id)) y la sustitución texto dado a .sub() (usando \g<id>).

+0

Gracias - desearía poder asignar dos respuestas correctas :-) –

+0

@Syed H: en igualdad de condiciones, su debe elegir la primera respuesta correcta en mi humilde opinión y eso es lo que hizo. Agregué mi respuesta solo como una alternativa ... Gracias por el comentario. – dawg

-1
rndStr = "20101215" 
rndStr2 = "20101216" 

print "Looking at dates between %s and %s" %(rndStr,rndStr2) 
+1

Lo mismo aquí, la cadena original tiene dos (diferentes) fechas, por lo que esto no funcionará. Gracias de cualquier manera. –

Cuestiones relacionadas