expresiones regulares

Hernan Martinez Foffani hernan en orgmf.com.ar
Jue Ago 1 22:15:32 CEST 2002


> 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
>>>



saludos,
-Hernan






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