Upload
alfonso-alba
View
1.023
Download
0
Embed Size (px)
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---