Python

Expresiones Regulares

¿Que son?

Poderoso lenguaje para hacer coincidir patrones de texto

Con Python el módulo 're' es el que les da soporte

match = re.search(pat, str)

re.search()

  •  Si la búsqueda es exitosa, retorna un objeto
  • Si no exitosa, retorna None 

Patrones básicos

  • a, X, 9, < -- caracteres ordinarios sólo coinciden con sí mismos de manera exacta. Los meta-caracteres que no coinciden con sigo mismos porque tienen un significado especial son:: . ^ $ * + ? { [ ] \ | ( )
  • . (un punto) -- coincide cualquier caracter (1 sólo) excepto por la línea nueva '\n'
  • \w -- (w minúscula) coincide un caracter de "palabra": es decir, una letra o dígito o guión bajo [a-zA-Z0-9_]. \W (W mayúscula) coincide cualquier caracter no-palabra.
  • \b -- límite entre palabra y no palabra

Patrones básicos (cont)

  • \s -- (s minúscula) coincide un solo caracter de espacio -- espacio, nueva línea, retorno, tab: [ \n\r\t\f]. \S (S mayúscula) coincide cuanquier caracter no-espacio.
  • \t, \n, \r -- tab, nueva línea, retorno
  • \d -- dígito decimal [0-9] (algunas utilidades viejas no lo soportan, pero todas soportan \w and \s)
  • ^ = comienzo, $ = fin -- coinciden el comienzo o fin de una cadena.
  • \ -- cancela lo "especial" de un caracter. Así, por ejemplo, utilizar \. para coincidir un punto.

Reglas

  • La búsqueda ocurre a lo largo de la cadena, parando en la primer coincidencia.
  • Todo el patrón debe coincidir, pero no en toda la cadena.
  • Si match = re.search(pat, str) es exitoso, match no es None y el texto encontrado está en match.group()

Las reglas básicas de las expresiones regulares para buscar un patrón en una cadena son

Ejemplos básicos

Chiste: what do you call a pig with three eyes? piiig!

Repetición

  •  + -- 1 o más ocurrencias del patrón a su izquierda. Ej: 'i+' = una o más 'i'es
  • * -- 0  o más ocurrencias del patrón a su izquierda
  • ? -- 0 o 1 ocurrencias del patrón a su izquierda 

Más a la izquierda y más grande

Primero encuentra la coincidencia de más a la izquierda del patrón, y segundo intenta usar todo lo que pueda de la cadena -- Ej. + y * abarcan lo más posible (el + y * son "codiciosos").

Ejemplo de repetición

Ejemplo con E-mail

Suponiendo que queremos encontrar la dirección de correo dentro de la cadena 'xyz alice-b@google.com mono violeta'

Notar que la búsqueda no devuelve todo el email porque  \w no encuentra '-''.'

Corchetes

  • Indican un grupo de caracteres
  • [abc] conciden 'a', 'b' o 'c'
  • \w, \s etc. funcionan dentro de los corchetes
  • El punto (.) no funciona en los corchetes, significa solamente punto literal.
  • Se puede usar el guión para indicar un rango: [a-z] encuentra todas las minúsculas.
  • Para buscar guiones, colocarlo al final: [abc-].
  • Un acento circumflejo al comienzo de corchetes busca el inverso: [^ab] busca cualquier caracter menos a o b

Extracción de grupos

  • Permite extraer partes de una búsqueda
  • cada parte va entre paréntesis
  • Los paréntesis no cambian el patrón de búsqueda
  • match.group(1) el la coincidencia en el primer paréntesis
  • match.group() sigue devolviendo la coincidencia completa

findall

Encuentra todas las ocurrencias del patrón

En archivos

# Open file
f = open('test.txt', 'r')
# Alimenta el archivo de texto en findall(); retorna una 
# lista de todas las cadenas encontradas
strings = re.findall(r'algun patron', f.read())

findall y Grupos

  • El mecanismo de paréntesis de grupos se puede combinar con findall
  • Si hay 2 o más paréntesis, el valor retornado es una lista de tuplas

Flujo de trabajo y depuración

  • Los patrones de expresiones regulares empaquetan mucho significado en unos pocos caracteres
  • Si el patrón no encuentra nada, hacerlo más débil quitándole partes.
  • Una vez que se obtienen muchos resultados, ajustarlo incrementalmente hasta lograr lo que se quería.
  • Herramientas en línea: http://www.regexr.com/  http://regex101.com/ 

Opciones

  • IGNORECASE -- ignora las diferencias entre mayúsculas y minúsculas.
  • DOTALL -- permite que el punto (.) coincida con una nueva línea -- normalmente coincide con cualquier cosa menos una nueva línea (aunque es mejor usar \s* para esto).
  • MULTILINE -- Permite que ^ and $ coincidan con el comienzo y fin de cada línea. Normalmente ^/$ sólo coinciden con el inicio y fin de toda la cadena.

Las funciones de re aceptan opciones para modificar su comportamiento, la opción se agrega como un argumento extra a search() o findall() ,ej: re.search(pat, str, re.IGNORECASE)

Codicioso y no-codicioso

  • Ejemplo de cadena: <b>foo</b> y <i>asi vamos</i>
  • Nuestro patrón: (<.*>)
  • Probar!
  • El aspecto codicioso de .* Provoca que coincida con toda la cadena.
  • Recordar que .* va todo lo lejos que puede en vez de frenar en la primer coincidencia! > codicioso
  • Se puede agregar un ? para hacerlo no-codicioso
  • Si hacemos (<.*?>), devuelve <b>, </b>, etc.
  • ? es una extensión, no todos los engines lo reconocen
  • los corchetes [] con ^ combinados excluyen el patron dentro de la búsqueda. Probar [^>]*

Substitución

  • re.sub(patron, reempazo, cadena) busca todas las coincidencias de cadena, y las reemplaza
  • La cadena de reemplazo puede incluir '\1', '\2' que se refieren a group(1), group(2), etc del patrón original
import re
str = 'xyz alice-b@google.com mono violeta bob@abc.com bla lavaplatos'

## re.sub(patron, reemplazo, cadena) -- retorna una nueva cadena con
## todo reemplazado, \1 es group(1), \2 group(2) en el reemplazo
print re.sub(r'([\w\.-]+)@([\w\.-]+)', r'\1@yo-yo-dyne.com', str)

Material de lectura extra

python-expresiones-regulares

By Guillermo Nuñez

python-expresiones-regulares

  • 3,114