Las expresiones regulares son el típico ejemplo de las cosas
que si no las usan con frecuencia se olvidan y tienes que ir tirando de Google
para recordarlas.
Por si no las conocéis todavía, son una gran ayuda a la hora
de buscar y reemplazar textos, aunque tienen una pequeña curva de aprendizaje.
Una vez superada, no puedes vivir sin ellas.
Tiene soporte en los lenguajes, entornos de desarrollo y en
los editores de textos más conocidos.
Podemos practicar las búsquedas con Notepad++, un editor free source code muy completo.
Una guía de referencia rápida de expresiones regulares que
suelo consultar es http://msdn.microsoft.com/es-es/library/az24scfc.aspx
Tienes más info en
Repasemos con ejemplos más útiles.
Caracteres
.
|
Cualquier carácter que no sea el
salto de linea \n
|
m.sa
|
La masa
está en la mesa
de la musa
|
[chars]
|
Coincide con cualquier carácter de
los especificados
|
m[ae]sa
|
La masa está en la mesa de la musa
|
[^chars]
|
Cualquier carácter de los que NO estén
encerrados por corchete
|
[^aem]
|
mesa
18
|
\t
|
Caracter de tabulación
|
\r
|
Caracter de Retorno de carro
(ASCII 13)
|
\n
|
Caracter de Nueva Linea (ASCII 10)
Recordad que el salto de línea de Windows es \n\r (chr 10 + chr 13) |
\
|
Seguido de un carácter, es la
forma de representar ese carácter si coincide con símbolos reservados. P.Ej, \.
\* \( \)
|
\x00
|
Caracter ascii especificado en
hexadecimal.
Por ejemplo, “\x23” seleccionará “#” (ascii 35) |
Clases de carácter
\w
|
Cualquier carácter numérico o letra
|
|
\w
|
P#5.8
|
|
\W
|
Cualquier carácter que no sea numérico o letra
|
|
\W
|
P#5.8
|
|
\s
|
El carácter de espacio en blanco
|
|
\S
|
Cualquier caracter que no sea un espacio en
blanco
|
|
\d
|
Cualquier dígito decimal
|
|
a18
|
||
\D
|
Cualquier carácter que no sea un dígito
decimal
|
|
a18
|
Cuantificadores
Los cuantificadores añaden cantidad de repeticiones a los
caracteres
*
|
Repetición ninguna o más veces
|
+
|
Repetición una o más veces
|
Ej: Cualquier número que se repita una o más
veces
|
|
\d+
|
d189b40h
|
?
|
Cero o una vez
|
Ej: Cualquier cifra, seguida opcionalmente de una
letra, y otra cifra
|
|
\d\w?\d
|
1A9 19 1
|
{n}
|
Exactamente N veces
|
Ej de extracción de una fecha: 2 digitos, la
barra /, 2 digitos, la barra /, 4 digitos
|
|
\d{2}/\d{2}/\d{4}
|
El 15/08/2014 llegaré a 2/300
|
{n,}
|
Al menos N veces
|
Elíge las palabras de al menos 3 letras
|
|
\w{3,}
|
arbol, ale,
so
|
{n,m}
|
De N a M veces
|
Ej de extracción de una fecha que puede contener
1 o 2 digitos en días y meses, y 4 digitos en año
|
|
\d{1,2}/\d{1,2}/\d{4}
|
El 15/8/2014 llegaré a 2/300
|
Anclajes
^
|
Inicio de línea
|
|
Selecciona la línea entera que empieza por número
|
||
^\d.*$
|
frase 1.
2
frase
Frase 3.
|
|
$
|
Fin de línea
|
|
Selecciona la última palabra que no acabe en
punto
|
||
\w+[^.]$
ó
\w+$
|
La frase 1.
La 2ª frase
Frase numero 3.
|
|
\b
|
Marca la posición de una
palabra limitada por espacios en blanco, puntuación o el inicio/final de una
cadena.
|
|
Ej: Selecciona las palabras que comiencen por
vocal
|
||
\b[aeiou]\w*\b
|
encina,pino,
romero,olmo
,almendro,cerezo.
|
Greedy
and Lazy (búsquedas tardías y tempranas)
Por defecto, todas estas búsquedas que hemos visto son búsquedas tardías.
Es decir, tienden a englobar el mayor número de elementos.
Si hacemos una búsqueda de los tags <span> de un html devolverá del primero al último.
Si hacemos una búsqueda de los tags <span> de un html devolverá del primero al último.
<span>.*</span>
|
Esta es la <span>casa</span> con las mejores <span>vistas</span>
|
Como veis, el modo tardío ha seleccionado desde el primer
span al último span, incluyendo el texto del medio. Si queremos cambiar el comportamiento de tardío
(greedy) a tempranp (lazy), usaremos el símbolo ?
<span>.*?</span>
|
Esta es la <span>casa</span>
con las mejores <span>vistas</span>
|
Grupos
Los grupos se pueden usar para posicionarnos en un punto de
la búsqueda sin llegar a seleccionarlo. Es algo duro de entender, pero con un
ejemplo se ve mejor.
En el ejemplo anterior, vimos que con la expresión regular <span>.*?</span>
seleccionábamos los span, incluyendo los tags. Si lo que queremos es seleccionar
el CONTENIDO del span haciendo referencia al propio tag SPAN sin seleccionarlo,
los introduciremos dentro de grupos de
búsqueda anterior y posterior.
(?<=expr) posiciona el resultado de la búsqueda tras el resultado
de expr, sin llegar a seleccionar la expresión
(?=expr) posiciona el resultado de la búsqueda justo donde
comienza la expresión, sin llegar a seleccionarla
Con lo que podemos conseguir seleccionar el contenido de 2
tags html
(?<=<span>).*?(?=</span>)
|
Esta es la <span>casa</span> con las mejores <span>vistas</span>
|
Con los grupos también podemos usar condicionales, es decir,
si se cumple una condición u otra
En este caso, elegiremos entre las marcas de inicio de
palabra, las fechas que sean 1 o 2
cifras, barra, 1 o 2 cifras , barra, y o 2 o 4 cifras
\b\d{1,2}/\d{1,2}/(\d{4}|\d{2})\b
|
El 15/8/2035
llegaré a 2/300
El 3/12/15
llegaré a 2/300
El 3/12/340 llegaré a 2/300
|
Otra característica de los grupos es que los resultados los
podemos introducir en variables para tratarlos desde c#.
Un grupo puede definirse con nombre o con índice.
(expr) Grupo con
índice
(?<nombre>expr) Grupo con nombre de variable
^\w+,\sa\s(?<DIA>\d{1,2})\sde\s
(?<MES>\w+\b)\sde\s(?<AÑO>\d{4})$
|
Valencia,
a 4 de febrero de 2018
Madrid,
a 15 de abril de 2019
|
Traducido “al castellano”, quedaría de la siguiente forma:
“Desde el inicio de la línea, selecciona letras hasta llegar
a una coma, un espacio, una “a”, un espacio, 1 o 2 dígitos que los introduces
en la variable “DIA”, un espacio, “de”, un espacio, texto que lo introduces en
la variable “MES”, un espacio, “de”, un espacio, 4 dígitos que los introduces
en la variable “AÑO”
Otro ejemplo de grupos: Extraer fechas que están en un formato algo mezclado
^\w{2}(?<AÑO>\d{4})(?<MES>\d{2})(?<DIA>\d{2})_
(?<H>\d{2}):(?<M>\d{2}):(?<S>\d{2})\.txt$
|
DW20141128_08:59:48.txt
UP20141115_09:39:46.txt DW20141106_11:45:20.txt |
Pasado a c#, este ejemplo se quedaría de la siguiente
manera.
Ejemplos
para validaciones
IBAN (España)
|
ES\d{2}[ ]\d{4}[ ]\d{4}[ ]\d{4}[ ]\d{4}[
]\d{4}|ES\d{22}
|
Codigo postal
|
^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$
|
Número
telefono (España) |
^[0-9]{2,3}-? ?[0-9]{6,7}$
|
Visa
|
^((67\d{2})|(4\d{3})|(5[1-5]\d{2})|(6011))(-?\s?\d{4}){3}|(3[4,7])\
d{2}-?\s?\d{6}-?\s?\d{5}$
|
Contraseña segura
|
(?!^[0-9]*$)(?!^[a-zA-Z]*$)^([a-zA-Z0-9]{8,10})$
|
URL
|
^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)(
[a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?$
|
Correo electrónico
|
^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|((
[a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$
|
Conclusión
Las expresiones regulares, como habéis podido comprobar, es una
herramienta muy potente que nos puede sacar de muchos apuros y ahorrarnos
docenas de bucles infernales para trastear con textos.
Espero que os sea de provecho.