regex, buscar cadenas con comillas

Oswaldo Hernández listas en soft-com.es
Lun Dic 10 16:31:05 CET 2007


Chema Cortes escribió:
> El 7/12/07, Oswaldo Hernández <listas en soft-com.es> escribió:
>> Antonio Beamud Montero escribió:
>>> El vie, 07-12-2007 a las 13:30 +0100, Oswaldo Hernández escribió:
>>>> Hola a todos,
>>>>
>>>> Estoy intentando localizar en una string cadenas que van entre comillas.
>>>>
>>>>  >>> c = "cadena de ejemplo con 'texto entre comillas'. Fin"
>>>>  >>> m = re.split("('.*')|(\".*\")", c)
>>>>  >>> m
>>>> ['cadena de ejemplo con ', "'texto entre comillas'", None, '. Fin']
>>>> Hasta aqui bien (excepto que no entiendo el None).
>>>> El problema se me presenta cuando hay mas de un texto entrecomillado:
>>>>
>>>>  >>> c = "cadena de ejemplo con 'texto entre comillas' y 'otro texto mas'. Fin"
>>>>  >>> m = re.split("('.*')|(\".*\")*", c)
>>>>  >>> m
>>>> ['cadena de ejemplo con ', "'texto entre comillas' y 'otro texto mas'", None, '. Fin']
>>>>
>>>> En este caso me toma desde la comilla inicial del primer texto hasta el cierre del ultimo como una
>>>> sola cadena.
>>>
>>> A bote pronto, con que cambies el .* por .*? para hacerlo non-greedy, te
>>> debe funcionar sin problemas.
>>>
>>  >>> c = "ejemplo con 'entre comillas', y 'otro mas' y \"un tercero\" Fin"
>>  >>> m = re.split("('.*?')|(\".*?\")", c)
>>  >>> m
>> ['ejemplo con ', "'entre comillas'", None, ', y ', "'otro mas'", None, ' y ', None, '"un tercero"',
>> ' Fin']
>>
>> Perfecto :)
> 
> Lo que no entiendo porqué usas .split() para localizar las cadenas. De
> ahí se explica que no entiendas porqué te salen los Nones.
> 

Lo que pretendia era hacer un replace unicamente en las cadenas que van entre comillas dejando el 
resto intacto. El split me parecio una buena idea ya que con esa expresion me devuelve todas las 
partes y en su orden.
Se que el regex tiene un 'replace', pero como no soy muy ducho con el, y corria un poquito de prisa 
al final quedo asi:

     def FiltraSQL(self, sql):
         # ajustes en sentencia sql antes de su proceso

         # dividir sentencia en fragmentos para modificar los entrecomillados y volver a montar
         partes = re.split("('.*?')|(\".*?\")", sql)
         # eliminar Nones
         while None in partes:
             partes.remove(None)

         for n,p in zip(range(len(partes)),partes):
             if p[0] == "'" or p[0] == '"':
                 partes[n] = p.replace("*", "%")

         return "".join(partes)

Imagino que se podrá optimizar bastante, pero de momento me ha valido.


> En principio, el split tenía que haberte sacado lo siguiente:
> 
> ['ejemplo con ', ', y ', ' y ', ' Fin']
> 
> O sea, te tenía que haber dividido la frase usando el patrón como
> separador. Pero al usar grupos de búsquedas (los paréntesis del
> patrón), el split incluye en el resultado las cadenas encontrada.
> Tienes dos grupos de búsqueda, que es lo que ves. El None indica uno
> de los grupos que no ha encontrado.
> 
> ¿Cómo habría que hacer para no sacara los grupos de búsqueda?
> Usando (?:...)
> 
> m = re.split("(?:'.*?')|(?:\".*?\")", c)
> 
> ¿Cómo tienes que hacer para que te dé sólo las cadenas que quieres buscar?
> 
> m = re.findall("(?:'.*?')|(?:\".*?\")", c)
> _______________________________________________
> Lista de correo Python-es 
> http://listas.aditel.org/listinfo/python-es
> FAQ: http://listas.aditel.org/faqpyes
> 
> 


-- 
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es