Perl6 expresiones regulares

Preview:

Citation preview

Programación en perlIntroducción a expresiones regulares

¿Qué es una expresión regular?

Una expresión regular es una plantilla o patrón que se compara con una cadena de texto.

El resultado de esta comparación es que la cadena de texto coincide o no coincide con ese patrón.

No existe “coincide a medias” o “casi coincide” o “esta parte sí pero esta otra no”

Ejemplo de uso

1.$_ = "yabba dabba doo";2.if (/abba/) {3.  say "¡Coincide!\n";4.}

En perl, las expresiones regulares forman parte de la propia sintaxis del lenguaje

Se evalúa el cuerpo del if si la secuencia ‘abba’ está en la cadena $_

Operadores

$string =~ /REGEXP/ -> devuelve verdadero si la cadena coincide con el patrón

$string !~ /REGEXP/ -> devuelve falso si la cadena coindice con el patrón

¿Cómo hay que leer un patrón?

El patrón /abba/ no es “la palabra abba”.

El motor de expresiones regulares interpreta el patrón como:

un caracter a seguido de un caracter b seguido de un caracter b seguido de un caracter a

Cuantificadores+ carácter precedente aparece 1 o más veces

ejemplo: /a+lfonso/

* carácter precedente aparece 0 o más veces

ejemplo /a*lfonso/

? carácter precedente aparece una o ninguna vez

ejemplo /alfon?so/

{min,max} número mínimo y máximo de ocurrencias

ejemplo /alfons{4,6}o/

. y []. cualquier carácter distinto de \n

ejemplo /a.*lfonso/

¿qué ocurre si aplicamos el patrón a la siguiente cadena:akksdffonsofonso?

[ ]! lista de opciones

ejemplo /[aA]lfons[oO]/

Admite rangos [a-z] [A-Z] [0-9]

Si queremos incluir el - tenemos que ponerlo al principio

[-aeiou]

[^ ]

[^ ] exclusión:

/\b[^aeiouAEIOU]/ primer carácter de una palabra siempre que este caracter no sea a, e, i, o, u, A, E, I, O, U.

Escapado

Si queremos incluir en el patrón alguno de los caracteres anteriores, hay que escaparlos

/www\.google\.com/

Posiciones

\b límite de palabra (espacio, tabuladores, puntos, comas, guiones, principio y fin de línea, etc)

/[aA]lfo?nso\b/

\B no debe haber un límite de palabra

/\Bola/

^ principio de cadena

$ fin de cadena

Posiciones

Dada la cadena:

Este es un curso de perl.

¿Qué patrón dará una coincidencia positiva?

perl\b

perl\b$

perl\b\.$

( )

Se utilizan para agrupar partes de un patrón.

/pepe+/ encajaría con pepeeeeeee

/(pepe)+/ encajaría con pepepepepepe

Cuidado con /(pepe)*/ esto encajaría con cualquier patrón

( )Los paréntesis permiten reutilizar parte de la cadena coincidente dentro de la propia expresión regular:

/(.)\1/ encuentra cualquier carácter que vaya seguido de sí mismo.

Se pueden poner varios paréntesis dentro de una misma expresión regular.

Perl los asignará a las referencias \1, \2, \3, etc según su orden de apertura ignorando la anidación.

/(OS ([Xx]) (.+))/ aplicado a la cadena OS X Lion

\1 ->OS X Lion

\2 -> X

\3 -> Lion

( )A partir de perl 5.10 es posible hacer referencia a un grupo usando la notación \g{N}

\1 -> \g{1}

Supongamos qué tenemos el siguiente patrón:

/(.)\111/ y la cadena aa11bb

Perlo no sabe si estamos diciendo \1 seguido de 11 o \11 seguido de 1 o \111

Para esto se utiliza la nueva notación

/(.)\g{1}11/

Alternativa: |

/luis|angel|pepe/ ->encajaría con cualquier cadena que contuviese luis o angel o pepe.

/Luis (y|o) Miguel/

Clases de caracteres

\d números

\s espacio, form-feed, tabulador, nueva línea y retorno de carro.

\R (perl 5.10) cualquier tipo de salto de línea (no tenemos que preocuparnos por el formato de fichero, sistema operativo, etc)

\w caracteres [a-zA-Z0-9_]

Opciones

/PATRON/OPCIONES

i no diferencia entra mayúsculas y minúsculas/pepe/i coincidiría con Pepe, pepe, PePe, PEPE

s hace que . también incluya el salto de línea

x hace que se ignoren espacios, tabuladores, comentarios y saltos de línea en la expresión regular:/ [0-9]+ # Esto es un comentario [#] # el caracter “#”/x

Variables especiales

$1, $2, $3 -> contienen la parte del patrón encerrada en su respectivo paréntesis

$& patrón encontrado

$` lo que precedía al patrón encontrado

$’ lo que sucede al patrón encontrado

Ejercicios

¿qué patrón usarías para localizar una página web como www.protrainning.com, mail.yahoo.com, etc?

Utilizando el fichero last.txt:

calcular todas las veces que se ha reiniciado el ordenador en el mes de noviembre

evaluar las veces que Alfonso ha entrado más tarde de las 8 y si supera las 5 veces, avisar de que es un vago.

Calcular la hora mínima y máxima a la que root ha accedido y el tiempo que ha estado activo.

Buscar y reemplazar

s/REGEXP/SUSTITUTO/opciones

Opciones:

i !ignora mayúsculas y minúsculas

g!busca y sustituye todas las ocurrencias

e!considera SUSTITUTO una expresión y la evalúa

s/\d{3,8}/9*9/e -> sustituye 456 por 81

Ejemplos de patrones

Localizar variables en un script perl

my\s+[$@%][a-zA-Z][a-zA-Z_]*\b

Ejemplos de patronesLocalizar una IP:

Es importante saber qué buscamos para definir nuestra expresión regular

¿nos vale este patrón \d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}

Depende, ya que este patrón encuentra 999.999.999.999 que no es una IP válida

Podemos capturar cada número en $1, $2, $3, $4 y validarlo a posteriori

Podemos utilizar este patrón[01]?\d?\d|2[0-4]\d|25[0-5] \. [01]?\d?\d|2[0-4]\d|25[0-5] \.[01]?\d?\d|2[0-4]\d|25[0-5] \. [01]?\d?\d|2[0-4]\d|25[0-5]

Ejemplos de patronesLocalizar números en coma flotante

primer intento:! [-+]?[0-9]*\.?[0-9]*

MALO: ENCAJA CON CUALQUIER CADENA YA QUE TODOS LOS CARACTERES SON OPCIONALES

segundo intento:: lo que es opcional es el decimal y los números siguientes, debe haber al menos un número

[-+]?[0-9]+(\.[0-9]*)?

tercer intento: falta que encuentre números como .0098

lo hacemos utilizando un or

[-+]?[0-9]+(\.[0-9]*)?|[-+]?(\.[0-9]+)

Sigue sin funcionar ya que va a encontrar, por ejemplo 123.1234.1234

Si esta expresión regular es buena o no dependerá del contexto

Cuarto intento\s[-+]?[0-9]+(\.[0-9]*)?|[-+]?(\.[0-9]+)\s

“looking around”(?=...) -> mira hacia la derecha

(?<= ... ) -> mira hacia la izquierda

ejemplo /alf(?=onso)/ -> sólo encuentra la cadena “alf” si esta va seguida de “onso”

Estos operadores no consumen texto

ejemplo /(alf(?=onso)|onso)/

Sirven para encontrar posiciones:

Supongamos que tenemos un texto en el que hay muchos “alfono” en lugar de alfonso.

Podríamos utilizar la siguiente expresión para corregir el error:s/(?<=alfon)(?=o\b)/s/g

Ejercicio: dado un número 1234123 meter los separadores de miles, es decir, reescribir el número como 1.234.123

Ejercicios

Utilizando el fichero error.log.1.Con objeto de enviar este fichero a una lista de correo pública, se desea lo siguiente:

Sustituir las direcciones IP por XXX.XXX.XXX.XXX

Sustituir las versiones de los programas Apache, mod_jk, mod_ssl y open_ssl !! por la cadena ---obfuscated for security---

Recommended