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