jueves, 20 de marzo de 2025

 Las expresiones regulares en Python


    Las expresiones regulares son una serie de patrones que especifican la regla o norma que se ha de seguir para localizar coincidencias dentro de una cadena de texto .

 Para utilizar las expresiones regulares en Python  debemos  importar la librería re: import re

 

.search: Busca la primera coincidencia de texto1 dentro de texto2

 

Resultado = re.search(Texto1, Texto2)

Texto1: Texto que se busca en Texto2

Texto2: Texto donde se busca Texto1

 

Si Texto1 está dentro de Texto2, search devuelve un objeto tipo Match

 

 Resultado = <re.Match object; span=(pos1, pos2), match=  Texto_1>

Pos1 = posición de inicio de Texto1

Pos2 = Posición de fin de Texto1

 

Un objeto tipo Match es un objeto de coincidencia por lo que siempre tiene un valor booleano de True.

 

Resultado= re.search(patron, cadena_texto)

if Resultado:

    process(Resultado)

 

Se puede extraer información del objeto match con los siguientes métodos:

 

group( ): Retorna la cadena de caracteres que coincide con la expresión regular

start( ): Retorna la posición de inicio de la coincidencia

end( ): Retorna la posición final de la coincidencia

span( ): Retorna una tupla que contiene la posición inicial y final de coincidencia

 

Si no hay coincidencia devolverá None

 


.findall: Busca todas las coincidencias de texto1 dentro de texto2

 

Resultado = re.findall(Texto1, Texto2)

Texto1: Texto que se busca en Texto2

Texto2: Texto donde se busca Texto1

 

Si Texto1 está dentro de Texto2, search devuelve una lista con todas las coincidencias

 

 Resultado = [Texto1(1), Texto1(2), Texto1(3)… Texto(n)] para n coincidencias.

Len(Resultado) = n

 

Si no hay coincidencia devolverá None

 

 

 

Acento circunflejo (^) : Comprueba si un texto comienza por el string indicado.

 

Resultado = re.seach(‘^Hola’, Texto2)

 

^Hola’ = Se busca la cadena ‘Hola’ al principio de Texto2

Texto2 = Texto donde se busca al inicio ‘Hola

 

Esta acción es lo mismo que utilizar la función re.match(‘Hola’, Texto2)

 

 

 

Signo dollar ($) : Comprueba si un texto finaliza por el string indicado.

 

Resultado = re.seach(‘Hola$’, Texto2)

 

Hola$’ = Se busca la cadena ‘Hola’ al final de Texto2

Texto2 = Texto donde se busca al final ‘Hola

 

 

 

La utilización de corchetes [ ] en las expresiones regulares.

 

Esta opción permite localizar un conjunto de caracteres dentro de un texto con lógica tipo OR, es decir, coincidencias con alguno de ellos.

 

Resultado = re.search(‘[ad]’, Texto2)

 

Search devolverá un objeto match si el carácter ‘a’ o el carácter ‘m’ se encuentran dentro de Texto2, sino devolverá None.

 

Se puede hacer una búsqueda utilizando el rango de valores entre dos caracteres.

 

Resultado = re.search(‘[a-d]’, Texto2)

 

Search devolverá un objeto match si el carácter ‘a’, ‘b’, ‘c’ o ‘d’ se encuentran dentro de Texto2, sino devolverá None.

 

Este método es muy útil si queremos buscar alguna palabra con diversas posibilidades.

 

Resultado = re.search(‘car[áa]cteres’, Texto2)

Buscará dentro de Texto2  una coincidencia con ‘caracteres’ o ‘carácteres


Ejemplos:


Resultado: re.search(‘^[an]’, Texto2)

La variable resultado contendrá un match si Texto2 comienza con ‘a’ o con ‘n’. Si no es así devolverá None.

 

Resultado: re.search(‘[an]$’, Texto2)

La variable resultado contendrá un match si Texto2 finaliza con ‘a’ o con ‘n’. Si no es así devolverá None.

 

El metacarácter ^ dentro de los corchetes y al principio indica la “no coincidencia” con los caracteres que le siguen. 

 

Resultado: re.findall(‘^[^an]’, Texto2)

La variable resultado contendrá un match si Texto2 comienza con cualquier carácter que no sea  a’ o ‘n’. Si no es así devolverá None.

 

 

Los conjuntos predefinidos de caracteres

Las representaciones de conjuntos predefinidos de caracteres vienen precedidos de la barra inversa \,  y tenemos los siguientes:

 

\d: Coincide con cualquier dígito decimal

\D: Coincide con cualquier carácter que no sea un dígito

\s: Coincide con cualquier carácter de espacio en blanco

\S: Coincide con cualquier carácter que no sea un espacio en blanco

\w: Coincide con cualquier carácter alfanumérico

\W: Coincide con cualquier carácter no alfanumérico

 

En python se utiliza igualmente la barra inversa (\) para los literales de cadena o secuencias de escape, lo que podría crear un conflicto a la hora de crear un patrón de búsqueda en una expresión regular. Cualquier uso de uno de los valores predefinidos anteriores en una expresión regular generará en python un SyntaxWarning, ya que python no lo detecta como una secuencia de escape válida.

 

Para evitar este aviso, que podría generar posteriormente un Syntaxerror, se utiliza la notación de cadena row de python ‘r’ para los patrones de expresiones regulares. De esta manera cualquier valor predefinido anterior no será considerado por python como una secuencia de escape, sino como un valor literal de dos caracteres; la barra invertida (\) y el valor predefinido.

 

Ejemplo: re.search(r ‘\d\d’, texto2) à busca la primera secuencia de dos números seguidos en Texto2

 

 

 

La utilización de operadores de repetición.  

 

Las llaves { }:

 

Esta opción indica un rango de repeticiones que debe haber en el carácter que le precede.

 

Resultado = re.findall(r‘\d{3}’, Texto2)

 

Devuelve una lista cuyos elementos son la coincidencia de tres números seguidos en Texto2.

 

Ejemplo: Texto2 = “1234p45r456345-123-08

Resultado = [‘123’, ‘456’, ‘345’, ‘123’]

 

Podemos indicar dos índices dentro de las llaves. El primero indica el mínimo de repeticiones y el segundo el máximo de repeticiones.

 

Resultado = re.findall(r‘\d{2,4}’, Texto2) nota: Sin espacios entre los índices y la coma

 

Devuelve una lista con todas las agrupaciones posibles de 4, 3 y 2 caracteres en Texto2. Primero intentará hacer agrupaciones del índice mayor, y si no es posible luego intentará hacerlas con el índice inmediato inferior, y así sucesivamente hasta llegar al índice menor.

 

Ejemplo: Texto2 = “1234p45r456345-123-08

Resultado = ['1234', '45', '4563', '45', '123', '08']

 

Al realizar la agrupación ‘4563’ los siguientes números disponibles son ‘45’. Como no puede agrupar 4 números, lo intenta con 3. Como no puede agrupar tampoco 3 números lo intenta con 2. En este caso se produce la agrupación ‘45’.

 

Cuando utilizamos caracteres concretos podemos indicar la agrupación de estos con las llaves

 

Texto2 = "1234p45r456234135-123-08"

Resultado = re.findall('[123]{2}', Texto2)

 

Busca todos los resultados posibles de los conjuntos de caracteres indicados entre corchetes agrupados de dos en dos dentro de Texto2 en una lista.

 

Resultado = ['12', '23', '13', '12']

Localizados en "1234p45r456234135-123-08"

 

 


El signo *:

 

Este metacarácter indica que el carácter que le precede puede repetirse 0 o más veces seguidas.

 

Texto2 = "123334p45r456-124123234135-123-08"

Resultado = re.findall('23*4', Texto2)

 

Devuelve una lista con las agrupaciones de números que empiezan por 2 y acaban por 4, teniendo en medio 0 o más números 3.

 

Resultado =['23334', '24', '234']

Lo coge de = "123334p45r456-124123234135-123-08"

 

 

 El signo +:

 

Este metacarácter indica que el carácter que le precede puede repetirse 1 o más veces seguidas.

 

Resultado = re.findall(r'\d+', Texto2)

 

Devuelve una lista con las mayores agrupaciones de números que se puedan realizar

 

Ejemplo: Texto2 = "1234p45r456345-123-08"

Resultado = ['1234', '45', '456345', '123', '08']

 

El metacarácter + es lo mismo que {1,}

 

Ejemplo2:

Texto2= "1234p45r456345-123-08"

Resultado = re.search(r'-\d+', Texto2).group()

 

Busca en Texto2 la primera coincidencia que tenga un guión(-) seguido del mayor conjunto de números posibles, y devuelve la cadena de caracteres de la expresión regular del match que retorna re.search().

 

Resultado = ‘-123’

 

 

Los paréntesis ( ):

El uso de paréntesis dentro de un patrón de búsqueda localiza el conjunto unido de caracteres entre paréntesis a la vez que realiza un recorte de lo que devolverá el método utilizado.

 

Ejemplo1:

Texto2 = "1234p45r456345-123-08"

Resultado = re.findall(r'-\d{3}', Texto2)

 

Resultado = [‘-123’]

 

Si colocamos el paréntesis nos devolverá solo lo que se encuentre en él siempre que haya coincidencia con el total del patrón.

 

Resultado = re.findall(r'-(\d{3})', Texto2) nota: busca ‘-\d{3}’ pero devuelve ‘\d{3}’

 

Resultado = [‘123’]

 

 

Ejemplo2:

Texto2 = "123334p45r456-123123234135-123-08"

Resultado = re.findall('(123)+', Texto2)

 

Busca en Texto2 todas las coincidencias de la cadena ‘123’ o de agrupaciones de repeticiones de la misma cadena, por ejemplo ‘123123’ o ‘123123123’, etc… y devuelve el recorte (123) en una lista.

 

Resultado = ['123', '123', '123']

Localizados en "123334p45r456-123123234135-123-08"

 

La cadena ‘123123’ es única, debido al metacarácter +, pero se recorta la salida a (123)


 

 El punto . :

 

El uso del punto sustituye cualquier carácter en esa posición.

 

Texto2 = "1234p45r456234135-123-08"

Resultado = re.findall('.4', Texto2)

 

Busca cualquier conjunto de coincidencias entre un carácter cualquiera y el número 4 dentro de Texto2.

 

Resultado = ['34', 'p4', 'r4', '34']

Lo encuentra en "1234p45r456234135-123-08"

 

 

Ejemplo2:

 

Texto2 = "1234p45r456234135-123-08"

Resultado = re.findall('.{3}4', Texto2)

 

Busca cualquier conjunto de coincidencias entre tres caracteres cualesquiera seguidos del número 4 dentro de Texto2 y los devuelve en una lista.

 

Resultado = ['1234', '45r4', '6234']

Los localiza en "1234p45r456234135-123-08"

 

 

El signo ? :

 

El uso del signo ? indica que el carácter que le precede puede estar presente o no en el patrón de búsqueda.

 

Ejemplo:

Texto2 = "1234p45r456-124123234135-123-08"

Resultado = re.findall('23?4', Texto2)

 

Buscará todas las agrupaciones de números que empiecen por 2 y terminen por cuatro, entre el 2 y el 4 podrá haber un 3 o no.

 

Resultado: ['234', '24', '234']

Localizados en "1234p45r456-124123234135-123-08"

 

 

 Algunos ejemplos generales :

 

1)      Supongamos una lista con datos de empresas:

 

Lista_empresas = ["Automotor SL - 971345678 - B07123456",

 "Garaje Palma S.A - 695236456 - A-07456789",

 "Taller Planas SA - 789456123 - B 45123456",

 "Chapistería Olmo SA - 654321987 - B-45678945"]

 

El nif de las empresas está escrito de varias formas. Sin nada después de la letra, con guión o con un espacio. Extraer una lista con los NIf de las empresas.

 

import re

 

Lista_empresas = ["Automotor SL - 971345678 - B07123456",

 "Garaje Palma S.A - 695236456 - A-07456789",

 "Taller Planas SA - 789456123 - B 45123456",

 "Chapistería Olmo SA - 654321987 - B-45678945"]

 

for empresa in Lista_empresas:

    resultado = re.findall(r'\s([^\d-].?\d{8})',empresa)

    print (resultado)

 

Resultado:

['B07123456']

['A-07456789']

['B 45123456']

['B-45678945']

 

 

Estudiemos el patrón (r'\s([^\d-].?\d{8})

 

Busca agrupaciones de caracteres que…

r          à Trata los valores predefinidos \s y \d como caracteres literales en python

                 para evitar el SystaxWarning

\s        à Empiezan por un espacio

[^\d-] à El siguiente carácter nos un número ni un guión

.?        à Seguidamente puede haber cualquier carácter, espacio, etc o no haber nada

\d{8}  à Por último tenemos 8 números seguidos.

([^\d-].?\d{8}) à El paréntesis excluyendo el espacio nos devuelve únicamente el Nif

 


 

2)      Escribir una función que valide contraseñas con las siguientes normas.

1-. Mínimo 10 caracteres

2-. Mínimo una letra mayúscula y una minúscula

3-. Mínimo dos dígitos

4-. Mínimo dos caracteres especiales de los siguientes @$^/!?*&.

 

import re

 

def validarContrasenya(contrasenya):

    valida = True

    if len(contrasenya)< 10:

        print("La contraseña debe tener al menos 10 caracteres")

        valida = False

   

    minus = len(re.findall("[a-z]",contrasenya))

    if minus< 1:

        print("La contraseña debe incluir al menos una letra minúscula")

        valida = False

 

    mayus = len(re.findall("[A-Z]",contrasenya))

    if mayus< 1:

        print("La contraseña debe incluir al menos una letra mayúscula")

        valida = False

 

    numeros = len(re.findall("[0-9]",contrasenya))

    if numeros< 2:

        print("La contraseña debe incluir al menos dos números")

        valida = False

 

    caract = len(re.findall("[@$^/!?*&]",contrasenya))

    if caract< 2:

        print("La contraseña debe incluir al menos dos caracteres especiales")

        valida = False

 

    if valida:

        print("Contraseña válida") 

 


Llamadas a la función y resultados:

 

print("Evaluación contraseña 'jnjty3aej58*':")

validarContrasenya("jnjty3aej58*':")

print("\nEvaluación contraseña 'KLkvj@bvk23*a':")

validarContrasenya("KLkvj@bvk23*a")

print("\nEvaluación contraseña '$4kjG45':")

validarContrasenya("$4kjG45")

 

Resultados:

 

Evaluación contraseña 'jnjty3aej58*':

La contraseña debe incluir al menos una letra mayúscula

La contraseña debe incluir al menos dos caracteres especiales

 

Evaluación contraseña 'KLkvj@bvk23*a':

Contraseña válida

 

Evaluación contraseña '$4kjG45':

La contraseña debe tener al menos 10 caracteres

La contraseña debe incluir al menos dos caracteres especiales

 

 

 

Utilizar un patrón de expresión regular como un objeto:  re.compile

 

La función re.compile compila un patrón de expresión regular en un objeto de expresión regular.

 

Se creará una variable tipo re, a través de la función compile, que contendrá el patrón de la expresión regular. A partir de ahí, esa variable se podrá utilizar con el conjunto de métodos incorporados en la librería re para aplicar el patrón a las cadenas de texto indicadas.

 

Ejemplo:

 

Variable_patron  = re.compile(patron)

Resultado= variable_patron.match(Texto1)

 

Esto es equivalente a…

 

Resultado = re.match(Texto1)

 

La ventaja de crear el patrón como un objeto estriba en la reutilización de código para patrones muy habituales (comprobar la validez de contraseñas, datos comunes como Nifes, teléfonos, etc) ya que .compile es más rápido a la hora de buscar patrones.

 

 El ejercicio 1 del apartado anterior se podría codificar de la siguiente manera:

 

formato_nif = re.compile('\s([^\d-].?\d{8})')

 

for empresa in Lista_empresas:

    resultado = formato_nif.findall(empresa)

    print (resultado)

No hay comentarios:

Publicar un comentario

División de Ruffini

División de Ruffini
Pulsa para descargar

Tabla de Logaritmos

Tabla de Logaritmos
Pulsa la imagen para descarga