expresiones regulares

Jose Alejandro Perez Rubio perezj en si.uji.es
Vie Ago 2 10:32:59 CEST 2002


On Thu, 2002-08-01 at 22:15, Hernan Martinez Foffani wrote:
> > Pues nada, ya me ha quedado claro del todo, gracias a todos por
> > "expresar regularmente" ;)
> > vuestros conocimientos y asi hacer que vea la luz sobre el tema
> > este de las expreg en python :)
> >
> > Bueno, vere que opina mi profe de como prefiere que lo haga y a
> > ello me pondre. Sera casi como
> > volver a hacer la practica de compiladores de la carrera :(
> 
> que pena!  ya me habia entusiasmado y trate de resolverlo sin
> usar parsers...
> demas esta decir que yo tambien opino que la mejor solucion
> es con analizadores.  solo que me interesaba ver si es posible
> hacer algo no tan "bien hecho" :-)  que se pudiera resolver
> en muy poquitas lineas de codigo.
> 
> el tipo de predicados que aceptaria el programa difiere solo
> un poco de la sintaxis de python.  ej:
>   linux and ( vms or http and www)
> 
> el problema es que python no puede evaluar las palabras sueltas
> correctamente.  además hace falta el objeto sobre el cual se
> aplicaría el predicado.
> 
> si hacemos que dicho objeto fuera de clase X y que tuviera un
> metodo que evalue la condicion de verdad de una caracteristica
> dada:
> 
> >>> class X:
> 	def es_un(self, st):
> 		if st == "linux":
> 			return True
> 		return False
> 
> 
> >>> xx = X()
> >>> xx.es_un("linux")
> 1
> >>> xx.es_un("www")
> 0
> >>>
> 
> y si pudieramos transformar el predicado
>  p = "sun or ( linux and http)"
> por una expresion valida en python como:
>  e = "xx.es_un('sun') or ( xx.es_un('linux') and xx.es_un('http'))"
> 
> bastaria evaluar en python la expresion para obtengamos el
> resultado deseado:
> 
> >>> eval(e, {'xx': xx})
> 0
> >>>
> 
> la funcion de transformacion lo que tendría que hacer
> cambiar cada literal por xx.es_un('el_literal')
> exceptuando 'and' 'or' y 'not'.
> 
> def pred2expr(predicado):
>     import re
>     r1 = re.compile(r"(\w+)")
>     r2 = re.compile(r"xx.es_un\('(and|not|or)'\)")
>     return r2.sub(r"\1",
>                   r1.sub(r"xx.es_un('\1')",
>                          predicado))
> 
> lo que hace esta funcion es buscar todas las palabras
> (regexp r1: \w+ ) y reemplazarlas por xx.es_un(...)
> esto incluye a and, not y or por lo que la segunda
> expresion regular r2 busca los casos xx.es_un('and')
> etc. y los devuelve al original.
> 
> 
> lo bueno es que el propio python se encarga de chequear
> la sintaxis.
> 
> >>> e = pred2expr("pirulo (")  # <-- notar el ( demas
> >>> eval(e, {'xx':xx})
> Traceback (most recent call last):
>   File "<pyshell#46>", line 1, in ?
>     eval(e, {'xx':xx})
>   File "<string>", line 1
>     xx.es_un('pirulo') (
>                        ^
> SyntaxError: unexpected EOF while parsing
> >>>
> 

Jo! Que imaginación, te felicito, la idea es genial. Creo que esto
hace lo que queremos:

import re

def xx( reobj ):

  k = reobj.group()

  if k in [ 'and', 'or', 'not' ] :
    rdo = k
  else :
    if k == 'linux' :
      rdo = '1'
    else :
      rdo = '0'

  return rdo

p  = "sun or ( linux and http)"
print eval( re.sub( '\w+', xx, p ) )


Un saludo





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