29 de julio de 2018

Repasando python. Expresiones regulares. Resumen 1


Usando el módulo re (patrones-patterns estilo Perl). Módulo regex para estilo Emacs

Las expresiones regulares son un tipo especial de programación dentro de Python, cuyo objetivo es trabajar con cadenas de caracteres, para buscar coincidencias y así saber si las cadenas que tenemos, por ejemplo, son direcciones, emails, código de algún lenguaje, o multitud de otras aplicaciones. 

Patrones simples - Simple Patterns

Coincidencia de caracteres - matching characters

Por ejemplo, la cadena hola y la cadena hola coinciden exactamente. Si tenemos activado un modo de case-insensitive además coincidirán las cadenas Hola y HoLa exactamente.

En expresiones regulares usamos también caracteres especiales o metacaracteres. Estos metacaracteres representan no un carácter, sino un conjunto de ellos, o una repetición, etc. por lo que no coinciden en principio. Los metacaracteres son:

. ^ $ * + ? { } [ ] \ | ( )

[ ] - Brackets o corchetes.

Indican una clase de caracteres, bien uno a uno, o bien entre un rango (separados por un guión). Por ejemplo, para indicar las letras a, b y c, podemos escribir [abc] o [a-c]. Todas las letras minúsculas pueden ser [a-z].

Si escribo [abc$] aunque $ sea un metacaracter, dentro de una clase, se refiere al caracter $.

Clase complementaria. Uso el metacaracter ^. Por ejemplo, la clase de todos los caracteres excepto el 5 sería [^5].

\ - Backslash o barra diagonal invertida

Este metacaracter es muy importante. Indica que lo que le sigue es una clase especial. Por ejemplo:
  • \d --> Coincide cualquier dígito. Equivale a la clase [0-9].
  • \D --> Coincide cualquier carácter que no sea un dígito. Equivale a [^0-9].
  • \s --> Coincide cualquier carácter "espacio en blanco". Equivale a [ \t\n\r\f\v].
  • \S --> Coincide cualquier carácter que no sea "espacio en blanco". Equivale [^ \t\n\r\f\v].
  • \w --> Coincide cualquier carácter alfanumérico. Equivale a [a-zA-Z0-9_].
  • \W --> Coincide cualquier carácter no alfanumérico. Equivale a [^a-zA-Z0-9_].
También indica que si le sigue un metacaracter estamos analizando ese carácter. Por ejemplo , la referencia a \$ indica el carácter $.

Estas clases pueden formar, a su vez, otras clases. Por ejemplo, [\s,.] indica la clase de los caracteres espacios en blanco más el punto más la coma.

. Punto

El metacaracter punto '.' coincide con cualquier cosa excepto un carácter de nueva línea. El modo alternativo es re.DOTALL (incluso coincidiendo con una nueva línea). A menudo el punto se usa para indicar "cualquier carácter".

= = = = = = = =

Repitiendo cosas - repeating things

No sólo utilizamos las expresiones regulares para las coincidencias, sino para repetir cosas. Por ejemplo, la expresión ca*t (usando el metacaracter asterisco) coincidirá con ct (0 a carácter), cat (1 a), caaat (3 a caracteres). Se lee "a" cualquier número de veces...

Otro carácter de repetición es + (más). Funciona igual que * pero diferencia que no acepta 0 repeticiones del asterisco. Por eso ca+t no tiene coincidencia con ct. Se lee "a" por lo menos una vez...

El carácter ? indica la aparición una 0 cero veces. Por ejemplo home-?brew muestra coincidencia con homebrew y home-brew.


Y la última forma es {a,b}, repeticiones desde a veces hasta b veces. Por ejemplo a\{1,3}b indicará coincidencia con a\b , a\\b y a\\\b. 

* se puede expresar como {0,} , + como {1,} y ? como {0,1}, pero no se suele hacer.



= = = = = = = =

Usando expresiones regulares - Using Regular Expressions


Compilando expresiones regulares
Usamos el módulo re para compilar una expresión regular. 

>>> import re
>>> p = re.compile('ab*')
>>> p  
<_sre.SRE_Pattern object at 0x...>

También acepta banderas como

>>> p = re.compile('ab*', re.IGNORECASE)

Python trata las expresiones regulares como cadenas, y las pasa al módulo programado en C re.


The Backslash Plague - La plaga de la barra diagonal
Ya sabemos que se usa la barra invertida para denotar caracteres especiales o clases. Imaginemos que queremos compilar los caracteres \seccionEn este caso, tenemos que indicar el carácter literal de barra invertida con otra barra antecediéndola \\seccion al introducirlo en re.compile() . Pero si queremos expresarlo como una cadena lietral de Python, necesitamos "\\\\seccion"

Por eso a veces usamos en Python la notación raw: r"ab" (antecediendo con r).

Regular StringRaw string
"ab*"r"ab*"
"\\\\section"r"\\section"
"\\w+\\s+\\1"r"\w+\s+\1"

Representando coincidencias - Performing Matches
Tenemos los siguientes métodos o atributos, entre otros:


Method/AttributePropósito
match()Determina si la expresión regular coincide al principio de la cadena.
search()Busca por toda la cadena, buscando la localización donde coincida
findall()Encuentra todas las subcadenas que coincidan con la expresión y las devuelve en forma de lista.
finditer()
Encuentra todas las subcadenas que coincidan con la expresión y las devuelve en forma de iterador (iterator).

El resultado de un programa con match es o bien None (sin coincidencias) o un objeto tipo match con información sobre la misma.


import re
p = re.compile('[a-z]+')
m = p.match("tiempo")
print m

En este caso el resultado es <_sre.SRE_Match object at 0x7f2749ff3648>

Para extraer información de este objeto, necesitamos varios métodos o atributos. Entre los más importantes tenemos:

Métodos / atributosPropósito
group()Devuelve la cadena que coincide con la expresión regular.
start()Devuelve la posición inicial de la coincidencia.
end()Devuelve la posición final de la coincidencia.
span()Devuelve una tupla con la posición inicial y final.


import re
p = re.compile('[a-z]+')
m = p.match("tiempo")
print m.group()
print m.start(),m.end()
print m.span()

Dando como resultado

tiempo
0 6
(0, 6)

Otro ejemplo


# *-* coding: utf-8 *-*

import re
p = re.compile('[a-z]+')
# en este caso, dará None, ya que busca DESDE el principio de la cadena.
print p.match(":::message")
# En este caso, mostrará el objeto match, y se puede obtener información su aparición.
m=p.search(":::message")
print m
print m.group()
print m.span()

Dando como resultado

None
<_sre.SRE_Match object at 0x7fa9a11f3648>
message
(3, 10)


findall() devuelve una lista de cadenas coincidentes


>>> p = re.compile('\d+')

>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords fQa-leaping')

['12', '11', '10']

findall() tiene que crear la lista completa antes de devolverla como el resultado. El método finditer() devuelve objetos tipo match que pueden ser iterados.


>>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
>>> iterator 
<callable-iterator object at 0x...>
>>> for match in iterator:
...     print match.span()
...
(0, 2)
(22, 24)
(29, 31)


No hay comentarios:

Publicar un comentario