Regex o expresión regular es una herramienta de coincidencia de patrones y te permite buscar texto de una forma muy avanzada.
Regex es como el CTRL+F pero con esteroides.
Se utiliza mucho en programación y es realmente útil a la hora de manejar cantidades grandes de datos.
Por ejemplo, si quieres encontrar todos los correos electrónicos o números de teléfono a partir de una fuente de datos, regex puede hacer el trabajo.
La desventaja de las expresiones regulares es que lleva un tiempo memorizar todos los comandos. Se podría decir que se tarda 20 minutos en aprender, pero casi una eternidad en dominar.
En este tutorial, aprenderemos todo lo que necesitas saber para empezar a crear tus primeras expresiones regulares.
Para ello utilizaremos la herramienta online Regex101. Una herramienta online muy útil donde puedes practicar fácilmente expresiones que incluye documentación y ejemplos de uso. Además, podrás compartir tus expresiones regulares y guardarlas para volver a usarlas.
Te recomiendo escribir y probar cada expresión regular que veas en esta guía para entender realmente lo que estás haciendo.
Tutorial de Regex
Para que sea lo más útil posible, este tutorial está lleno de ejemplos. Esto significa que algunos de los conceptos de regex se introducen como parte de los ejemplos. ¡Te recomiendo leerlo todo!
Y vamos a empezar con las primeras expresiones regulares.
Regex y banderas (flags)
Una expresión regular (o regex) comienza con una barra inclinada (/) y termina con otra barra inclinada.
La coincidencia de patrones se produce entre estas barras.
Por ejemplo, busquemos la palabra «torpedo» en el siguiente texto.
Como puedes ver, esto funciona como el CTRL + F de cualquier programa.
Presta atención a la letra g en el regex /torpedo/g anterior.
La letra g significa que la bandera global está activada. En otras palabras, la expresión regular seguirá buscando todas las coincidencias a lo largo del texto. Sin ella, pararía al encontrar la primera coincidencia.
La mayor parte de las veces vas a utilizar la bandera «g» solamente.
Pero es bueno entender que hay unas cuantas más.
En el editor online de Regex101, puedes encontrar todas las banderas o flags disponibles en la esquina superior derecha.
Siguiendo con el caso anterior, si desactivo la bandera «g», verás como aparece sólo la primera coincidencia.
¿Simple verdad?
Sin embargo, el verdadero poder de las expresiones regulares aparece cuando buscamos patrones en lugar de palabras específicas.
Para hacer esto, necesitamos aprender los caracteres especiales de regex que hacen posible la coincidencia de patrones
Empecemos con el símbolo +.
El operador + – Coincidir con uno o más
Busquemos la letra «o» en el texto del ejemplo.
Esto coincide con todas las letras «o» que hay.
¿Pero qué pasa si quieres buscar varios caracteres «o» seguidos?
En este caso, puedes utilizar el carácter + después de la letra «s». Esto coincide con todas las letras «s» siguientes a la primera.
Como resultado, ahora coincide con la doble «s» del texto además de la «s» singular.
El resultado parece el mismo, pero si te fijas bien en los colores de las coincidencias, verás que en la primera imagen detecta todas las letras «o» como simples, mientras que en la segunda imagen, las letras «o» seguidas aparecen como una misma coincidencia.
En resumen, el operador + coincide con uno o más caracteres iguales seguidos.
Más adelante veremos ejemplos en los que esto resulta mucho más útil.
A continuación, veamos cómo funciona la concordancia opcional.
El operador ? – Coincidencia de caracteres opcionales
La coincidencia opcional utiliza el símbolo de interrogación (?).
La concordancia opcional significa coincidir con algo que podría seguir.
Por ejemplo, para que coincidan todas las letras «o» y todas las «o» seguidas de una «r», puedes especificar la letra «r» como coincidencia opcional utilizando el signo de interrogación.
Esto coincide con:
- Cada «o» singular.
- Cada combinación de «or».
A continuación, veamos un carácter especial que combina los caracteres + y ?
El operador * – Coincide con cualquier carácter opcional
El operador estrella (*) significa «coincide con cero o más».
Esencialmente, es la combinación de los operadores + y ?
Por ejemplo, hagamos coincidir cada letra «o» con cualquier cantidad de letras «r» que le sigan.
Esto coincide con:
- Todas las letras «o» singulares.
- Todas las combinaciones de «or».
- Todas las combinaciones de «orr».
De hecho, esto coincidiría con «orrrrrr» con cualquier número de letras «r» siempre que vayan precedidas de una «o».
A continuación, veamos el carácter comodín.
El Operador . – Coincide con cualquier carácter excepto una nueva línea
En regex, el punto es un carácter especial que coincide con cualquier carácter singular.
Actúa como comodín.
El único carácter con el que no coincide el punto es un salto de línea.
Por ejemplo, hagamos coincidir cualquier carácter que venga antes de «or» en el texto.
¿Pero qué tal si coincide con un punto entonces? El punto (.) es un carácter especial reservado, por lo que no se puede utilizar.
Aquí es donde se utiliza el escape.
El operador \ – Escapar un carácter especial
Si estás familiarizado con la programación, sabes lo que significa escapar.
Si no es así, escapar significa «invalidar» una palabra clave u operador reservado utilizando un carácter especial delante del mismo.
Como has visto en el ejemplo anterior, el carácter punto actúa como un comodín en regex. Esto significa que no puedes utilizarlo para que coincida con un punto en el texto.
Como puedes ver, la expresión /./g coincide con cada letra (y espacio) del texto, por lo que no es de mucha ayuda.
Aquí es donde el escape es útil.
En regex, puede escapar cualquier carácter reservado utilizando una barra invertida (\).
Todo lo que vaya seguido de una barra invertida se convertirá en un carácter de texto normal.
Para hacer coincidir los puntos usando regex, debes escapar el carácter de punto con la barra invertida.
Ahora coincide con todos los puntos del texto.
Juguemos con el ejemplo. Para que coincida con cualquier carácter que venga antes de un punto, debes añadir un punto antes del punto escapado.
Ahora ya sabes cómo emparejar y escapar caracteres en regex. Pasemos a la coincidencia de caracteres de palabras utilizando otros caracteres especiales.
Combinar diferentes tipos de caracteres
Acabas de aprender a utilizar la barra invertida para escapar un carácter.
Sin embargo, la barra invertida tiene otro uso importante. Combinando una barra invertida con algún carácter particular se forma un operador que puede ser usado para encontrar coincidencias útiles.
Por ejemplo, un carácter especial importante en regex es \w.
Esto coincide con todos los caracteres de la palabra, es decir, letras y dígitos, pero deja fuera los espacios.
Por ejemplo, vamos a hacer coincidir todas las letras y dígitos del texto:
Otro operador especial muy utilizado es el carácter de espacio \s que coincide con cualquier tipo de espacio en blanco que haya en el texto.
Por ejemplo, hagamos coincidir todos los espacios del texto.
Por supuesto, también puede coincidir sólo con caracteres numéricos.
Esto ocurre mediante el operador \d.
Por ejemplo, hagamos coincidir todos los dígitos del texto.
Esto coincide con 2 y 0.
Estos son los operadores de caracteres especiales más básicos que hay en regex.
A continuación, vas a aprender a invertir estos caracteres especiales.
Invertir caracteres especiales
Para invertir un carácter especial en regex, debes ponerlo en mayúsculas.
- \w coincide con cualquier carácter de palabra -> \W coincide con cualquier carácter que no sea de palabra
- \s coincide con cualquier carácter de espacio en blanco -> \S coincide con cualquier carácter de espacio no blanco.
- \d coincide con cualquier dígito -> \D coincide con cualquier carácter que no sea un dígito.
Ejemplos:
A continuación, veamos cómo encontrar palabras con una longitud específica.
{} – Coincidir con una longitud específica
Supongamos que quieres capturar todas las palabras que tienen más de 2 caracteres.
Ahora, no puedes usar + o * con el carácter \w ya que no tiene sentido.
En su lugar, debes utilizar las llaves {} especificando cuántos caracteres deben coincidir.
Hay tres formas de usar {}:
- {n}. Coincidir con n caracteres consecutivos.
- {n,}. Coincidir con n caracteres o más.
- {n,m}. Coincidencia entre n y m de longitud.
Veamos ejemplos de cada uno.
Ejemplo 1. Coincide con todos los conjuntos de caracteres que tienen exactamente 3 de longitud:
Ejemplo 2. Coincide con cadenas consecutivas de 3 caracteres o más:
Ejemplo 3. Coincide con cualquier conjunto de caracteres que tengan entre 3 y 5 caracteres de longitud:
Ahora que ya sabes cómo tratar las cantidades en regex, vamos a hablar de la agrupación.
[] – Grupos y rangos
En regex, puedes agrupar caracteres. De esta forma se busca una coincidencia con cualquier carácter del grupo.
Una forma de agrupar caracteres es utilizando los corchetes [ ].
En el siguiente ejemplo coincidirán dos letras cualesquiera en las que la última letra sea una r y la primera sea una a o una e:
Una ventaja del uso de corchetes es que puedes especificar un rango. Esto te permite buscar coincidencias con cualquier letra en el rango especificado.
Para especificar un rango, se utiliza el guión. Por ejemplo, la expresión [a-z] coincidirá con cualquier letra de la a a la z.
Por ejemplo, en la siguiente expresión coincidirá cualquier grupo de dos letras que termine en r y comience con cualquier letra de la a a la z:
A veces necesitarás combinar rangos. Esto también es posible en regex.
Por ejemplo, para encontrar dos letras cualesquiera que terminen en r y comiencen con cualquier letra minúscula o mayúscula, puedes usar [a-zA-Z]s.
Si necesitas encontrar dos caracteres cualesquiera que terminen en s y empiecen con un número entre 0 y 9, puedes usar [0-9]s
¿Sencillo no?
A continuación, veremos otra forma de agrupar caracteres en regex.
() Captura de grupos
En regex, los grupos de captura son una forma de tratar varios caracteres como una sola unidad.
Para crear un grupo de captura, debes colocar los caracteres dentro de paréntesis.
Por ejemplo, con la expresion regular (e|E)s coincidirán todas las agrupaciones de la letra e mas la letra s tanto si la e es mayúscula como minúscula.
Pero, ¿por qué los paréntesis? Veamos qué ocurre sin ellos:
Ahora coincide con cualquier letra e o con las letras Es.
Esta es la gracia de los grupos de captura. Trata los caracteres dentro del paréntesis como uno solo.
Veamos otro ejemplo en el que encontramos cualquier palabra que tenga entre 2 y 3 letras y cada letra de la palabra sea e, a, r.
Como último ejemplo de captura, busquemos cualquier palabra que repita ar dos o tres veces seguidas.
Aquí el ar no coincide con las palabras cargadoo o ahorarr. Esto se debe a que el ar sólo aparece una vez. Sin embargo, el mamaarararar del final tiene 4 veces ar, por lo que coincide en 2 y en 3 repeticiones. Como puedes ver, el último ar no queda seleccionado porque ya sería la 4a coincidencia.
A continuación, echemos un vistazo a otro carácter especial, el signo de interrogación (^).
El operador ^ – Coincidir con el inicio de una línea
El carácter ^ en regex significa coincidir con el comienzo de la nueva línea.
Por ejemplo, busquemos una coincidencia con la letra L al principio del texto.
Ahora, veamos qué ocurre cuando intentamos hacer coincidir la letra S del principio de la siguiente frase.
No hay coincidencias.
Pero, ¿por qué? Hay una S al principio de la segunda línea.
Esto sucede porque el flag o bandera está configurada como global (Recuerda, arriba a la derecha). Estamos tratando todo el texto como si fuera una sola línea.
Para solucionar esto, hay que seleccionar tambien la bandera multilínea además de la bandera global.
Ahora la coincidencia también aparece al principio de la segunda línea.
Sin embargo, es más fácil tratar el texto como un todo, así que vamos a desactivar la bandera multilínea para el resto de la guía.
Ahora que sabes cómo funciona el operador ^ en regex, echemos un vistazo al siguiente carácter especial, el símbolo del dólar $.
$ Final de una línea
Para hacer coincidir el final de una línea con regex, debemos utilizar el símbolo del dólar $.
Por ejemplo, busquemos una coincidencia con el punto que termina el texto.
Como puedes ver, sólo coincide con el punto al final del texto. Recuerda que esto sucede porque tratamos el texto como una sola línea de texto.
Ahora ya hemos aprendido la mayoría de los caracteres especiales que vamos a utilizar en regex.
Es hora de echar un vistazo a los conceptos lookahead (búsqueda hacia delante) y lookbehind (búsqueda hacia atrás).
Lookbehinds
En regex, un lookbehind significa coincidir X precedido de Y.
Hay dos tipos de lookbehinds:
- Lookbehind positivo
- Lookbehind negativo
Veamos lo que hacen.
El operador (?<=) – Lookbehind positivo
Un lookbehind positivo se especifica definiendo un grupo que comienza con un signo de interrogación, seguido de un signo menos que y un signo igual y luego un conjunto de caracteres: (?<=)
Aquí < significa que vamos a realizar un lookbehind, y = significa que es positivo.
Un lookbehind positivo coincide con todo lo anterior a la expresión principal sin incluirlo en el resultado.
Por ejemplo, vamos a buscar los primeros caracteres después de or en el texto.
Esta búsqueda positiva no incluye or en las coincidencias. En su lugar, comprueba si las coincidencias están precedidas por or antes de mostrarlas.
El operador (?<!) – Lookbehind negativo
Otro tipo de lookbehind es la negativa. Se trata básicamente de lo contrario al lookbehind positivo.
Para crear un look behind negativo, debemos crear un grupo con un signo de interrogación seguido de un signo menos que y un signo de exclamación: (?<!)
Aquí < significa mirar hacia atrás y el ! lo hace negativo.
Como ejemplo, realicemos exactamente la misma búsqueda que hicimos en el lookbehind positivo, pero en negativo.
Como puedes ver, la búsqueda negativa coincide con todo excepto con el primer carácter después de las letras or. Si te fijas, es exactamente lo contrario a la búsqueda positiva.
Ahora que sabes lo que hacen los lookbehinds, veamos como funcionan los lookaheads.
Lookaheads
En regex, como ya te habrás podido imaginar, un lookahead es similar al lookbehind.
Un lookahead coincide con todo lo que hay después de la expresión principal sin incluirlo en el resultado.
Para realizar un lookahead, todo lo que hay que hacer es eliminar el signo < de los lookbehind que hemos visto justo arriba.
- (?=) es un lookahead positivo.
- (?!) es un lookahead negativo.
El operador (?=) – Lookahead positivo
Por ejemplo, busquemos una coincidencia de cualquier símbolo seguido de ar.
Como te puedes imaginar ya, un lookahead negativo coincide exactamente con lo contrario a un lookahead positivo. Igual que en los lookbehinds.
El operador (?!) – Lookahead negativo
Por ejemplo, hagamos coincidir todo excepto los caracteres individuales que aparecen antes de ar.
Ahora ya tienes todas las herramientas para entender un ejemplo un poco más complejo. En el siguiente ejemplo práctico aprenderás como desarrollar una expresión regular paso a paso.
Buscar y reemplazar números de teléfono usando Regex
Imagina que tenemos un documento de texto que tiene números de teléfono en distintos formatos.
Nuestra tarea es encontrar esos números y reemplazarlos formateándolos todos de la misma forma.
El número de Ado es sencillo. Sólo 9 dígitos seguidos.
El número de Vayaseo es un poco más complicado porque hay que separar la expresión en 5 partes:
- Un grupo de tres dígitos
- Un guión
- Un grupo de tres dígitos
- Un guión
- Un grupo de tres dígitos.
Ahora tenemos la coincidencia con el numero de Vayaseo.
Pero nuestro objetivo es hacer coincidir todos los números al mismo tiempo. Ahora el número de Ado ya no coincide.
Para arreglar esto, necesitamos reestructurar la regex de nuevo. En lugar de asumir que siempre hay un guión entre los dos primeros grupos de números, vamos a asumir que es opcional. Como ya sabes, esto se puede hacer utilizando el signo de interrogación.
Sigamos.
El numero de Marc es igual que el de Vayaseo pero con espacios en lugar de guiones
Para tener esto en cuenta, debemos asumir que el separador es un espacio en blanco o un guión. Esto se puede hacer usando un grupo con corchetes [] colocando un guión y un espacio en blanco en él.
Ahora el número de Marc también coincide con nuestra expresión regular.
En el teléfono de Chuiso, los tres primeros dígitos están aislados por un paréntesis y los dos últimos grupos están separados por un guión.
Para encontrar estos números, tenemos que añadir un paréntesis opcional delante de los tres primeros dígitos. Pero como dijimos al principio del tutorial, el paréntesis es un carácter especial en regex, así que tienemos que escaparlos usando la barra invertida \.
Genial, ahora también encontramos el teléfono de Chuiso.
Por último, un número de teléfono puede estar formateado de manera que el código de país esté delante del número con un signo +.
Para tener esto en cuenta, tenemos que añadir un grupo opcional de un signo + seguido de dos dígitos entre 0-9.
Ahora nuestro regex encuentra todos los números de teléfono de la lista.
A continuación, vamos a sustituir cada número por un número tal que cada teléfono tenga el mismo formato.
Antes de poder hacer esto, necesitamos capturar cada conjunto de números creando grupos de captura para ellos. Como vimos antes, esto se hace colocando cada conjunto de dígitos en un conjunto de paréntesis.
En la sección Match Information que encontramos en la columna derecha, podemos ver que ahora cada conjunto de números de un número de teléfono está agrupado en los grupos de coincidencia. Concretamente en los grupos de captura 3, 4 y 5.
Sin embargo, hay un problema. Si seguimos bajando hasta el teléfono de Natalia, veremos que el número +34 aparece dos veces, en el grupo 1 y en el grupo 2.
Esto no es lo que queremos.
Esto sucede porque la expresión regular coincide tanto con el +34 con espacio como sin espacio. De ahí los dos grupos.
Para solucionar esto debemos al primer grupo de la expresion que no lo debe capturar.
Para ello, utilizaremos el operador ?: delante del grupo.
Ahora el teléfono de Natalia (y todos los demás también) está bien dividido en 4 grupos.
Por último, podemos utilizar estos cuatro grupos de captura para sustituir los números coincidentes por números con el mismo formato.
En regex, puedes referirte a cada grupo de captura con el símbolo $n, donde n es el número del grupo.
Para formatear los números, vamos a abrir la pestaña de sustitución en el editor. En el menú de la izquierda:
Digamos que queremos reemplazar todos los números con un número que tenga el siguiente formato:
+34 666-555-444
Y si no hay un +34 delante del número, entonces lo dejamos como:
666-555-444
Para ello, sustituye cada número de teléfono haciendo referencia a su grupo de captura en la sección Substitución del editor:
$1$2-$3-$4
¡Et voilà! Ahora todos los números se sustituyen en el texto resultante y siguen el mismo formato.
Con este ejemplo concluye este tutorial de regex.
Si tiene buena aceptación prepararé una segunda parte con más ejemplos prácticos enfocados al SEO y la creación de nichos.
Cualquier duda o sugerencia, puedes dejarla en los comentarios.
¡Hasta la proxima!