2011-08-19 28 views
5

tengo el siguiente texto:recuperar el texto en el interior # {}

#{king} for a ##{day}, ##{fool} for a #{lifetime} 

y la siguiente (roto) de expresiones regulares:

[^#]#{[a-z]+} 

que desea hacer coincidir todas las # {palabras} pero no el # # {words} (Doblar '#' actúa como escapar).

Hoy he notado que la expresión regular que tengo está ignorando la primera palabra (se niega a hacer coincidir # {king}, pero ignora correctamente ## {day} y ## {fool}).

>>> regex = re.compile("[^#]#{[a-z]+}") 
>>> regex.findall(string) 
[u' #{lifetime}'] 

¿Alguna sugerencia sobre cómo mejorar la expresión regular actual para adaptarla a mis necesidades? supongo que el problema es con [^#] ...

Respuesta

6

Usted tiene que usar una "aserción hacia atrás negativo", la expresión regular correcta se vería así:

import re 
t = "#{king} for a ##{day}, ##{fool} for a #{lifetime}" 
re.findall(r'(?<!#)#{([a-z]+)}', t) 

returns

['king', 'lifetime'] 

Explicación:

La expresión (?<!prefix)pattern coincide pattern sólo si no es precedida por prefix.

+0

Su solución es mejor, me olvidé de la mirada negativa detrás. – grep

+0

¿Funcionalidad? ¿Es este python regex específico? –

+0

@Andrei, no, parece que no es específico de Python (según [este sitio] (http://www.regular-expressions.info/lookaround.html)), pero dicen: "sabores como JavaScript, Ruby y Tcl do no soportan mirar hacia atrás en absoluto, a pesar de que sí respaldan la búsqueda anticipada ". – MatToufoutu

0

probar esto:

re.compile('^#\{[\w]+\}') 
+1

¿Lo intentó? Solo coincide con '# {king}' pero no con '# {lifetime}'. – hughdbrown

+0

Lo corrigí, debería funcionar ahora – prince

2

Utilice una construcción de búsqueda hacia atrás:

>>> s='#{king} for a ##{day}, ##{fool} for a #{lifetime}' 
>>> r=re.compile(r'(?:^|(?<=[^#]))#{\w+}') 
>>> r.findall(s) 
['#{king}', '#{lifetime}'] 
>>> 
2
>>> regex = re.compile("(?:^|[^#])#{[a-z]+}") 
>>> regex.findall(string) 
['#{king}', ' #{lifetime}'] 
>>> 
+1

Vale la pena señalar que el problema con esta solución (no utilizar la aserción negativa de mirar hacia atrás) es que no funcionaría para ''# {king} # {blah}'' - 'findall' devuelve coincidencias que no se solapan. –

1

Reemplazarlo por (?:^|[^#]). Como dijiste, solo [^#] significa un carácter que no es #, que obviamente no está al principio de la línea.

Cuestiones relacionadas