Tal como lo indica el título del artículo estamos buscando patrones pero de caracteres y dentro de un texto o cadena (string). Para ello usamos las expresiones regulares, tecnología presente en varios lenguajes de programación (PHP, Javascript, Phyton, Perl) que mediante una concatenación estructurada de caracteres nos permite moldear una fórmula o patrón para aplicar a un texto determinado y encontrar así las secuencias.
Cada vez que tengo que trabajar con ellos me veo con sentimientos encontrados. Por un parte sufro un poco ya que su sintaxis es muy compleja y difícil de memorizar, pero por otra parte me maravillo por todo lo que podemos hacer con un par de líneas de código.
Por ejemplo: Muchas plataformas no permiten que los usuarios envíen sus direcciones de correo electrónico en los mensajes que intercambian. Para ello cada mensaje pasa por un filtro de expresiones regulares. Aplicando el regexp (acrónimo de Regular Expressions) /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b/
podemos detectar estos caracteres tal como lo muestra la siguiente imagen:

Sintaxis
A modo de ejemplo, y para que luego lo podamos utilizar en nuestro WordPress, vamos a utilizar la nomenclatura y funciones propias de PHP. Verán en cada sintaxis, en la última columna, un enlace a la web regex101 donde podrán testear los ejemplos en vivo.
Caracteres
Regexp | Descripción | Resultado | regex101 |
. | Cualquier caracter | Tengo 36 años y mido 1,80m de altura. | 🔗 |
\s | Cualquier caracter de espacio en blanco | Tengo 36 años y mido 1,80m de altura. | 🔗 |
\S | Cualquier caracter que NO sea un espacio en blanco | Tengo 36 años y mido 1,80m de altura. | 🔗 |
\d | Cualquier caracter que sea un dígito entre 0 y 9 | Tengo 36 años y mido 1,80m de altura. | 🔗 |
\D | Cualquier caracter que NO sea un dígito entre 0 y 9 | Tengo 36 años y mido 1,80m de altura. | 🔗 |
\w | Cualquier caracter que sea una letra | Tengo 36 años y mido 1,80m de altura. | 🔗 |
\W | Cualquier caracter que NO sea una letra | Tengo 36 años y mido 1,80m de altura. | 🔗 |
Cuantificadores
Regexp | Descripción | Ejemplo | Explicación | Valores válidos | regex101 |
* | Cero o más | /v\d(\.\d)*/g | – Una «v» – un dígito – Cero o más de ( – un «.» – un dígito ) | WordPress v4.8. WordPress v4.8.3. WordPress 4.8 ❌ | 🔗 |
? | Uno o ninguno | /Star Wars\s?\d?/g | – Las palabras «Star Wars» – Uno o ningún espacio – Uno o ningún dígito | La película Star Wars La película Star Wars 4 La película Star Wars 5 La película StarWars ❌ | 🔗 |
+ | Uno o más | /v\d[.]\d+/g | – Una «v» – un dígito – un «.» – Uno o más dígitos | WordPress v4.8. WordPress v5.10. WordPress v5 ❌ | 🔗 |
{n} | Exactamente n veces | /w{3}/g | – Exactamente tres letras «w» | www.maugelves.com www.ayudawp.com desarrollowp.com ❌ | 🔗 |
{n,m} | Entre n y m veces | /\d{3,5}/g | – Entre 3 y 5 dígitos | Peugeot 306 Año 2017 20000 leguas de viaje submarino 12 monos ❌ | 🔗 |
{n,} | n o más veces | /\d{3,}/g | – Mínimo 3 dígitos | Peugeot 306 Año 2017 20000 leguas de viaje submarino 1000000 de años luz 12 monos ❌ | 🔗 |
Lógica
Sí, también se pueden agregar cierta lógica dentro de la misma expresión. Echa un ojo a los siguientes ejemplo:
Regexp | Descripción | Ejemplo | Explicación | Valores válidos | regex101 |
| | Operador OR (ó) | /Batman|Superman/g | – La palabra «Batman» ó «Superman» | Batman Superman Robin ❌ | 🔗 |
( … ) | Agrupador Este grupo puede luego ser reutilizado. | /Mar(cos|tín)/g | – Los caracteres «Mar» seguidos de – «cos» ó «tín» | Marcos Martín Mauricio ❌ | 🔗 |
(?(1)yes|no) | Condicional Si el grupo 1 entonces «yes» Sino «no» | /(Esta condición)?(?(1) es verdadera| es falsa)/g | – Uno o ninguna aparición de los caracteres «Esta condición» – Si existe concatena la búsqueda de los caracteres «es verdadera» – Caso contrario concatena la búsqueda de los caracteres «es falsa» | Esta condición es verdadera Esta otra es falsa Aquí no se debe seleccionar nada ❌ | 🔗 |
(?=…) | Futuro positivo (Positive Lookahead)
Solo encuentra patrones si existe una condición futura. | /para(?=psicología|normal)/g | – Seleccionará los caracteres «para» solo si: – los siguientes caracteres son «psicología» ó «normal» | La parapsicología. Fenómeno paranormal. El parapente. ❌ | 🔗 |
(?!…) | Futuro negativo (Negative Lookahead)
Solo encuentra patrones si no existe una condición futura. | /para(?!psicología|normal)/g | Selecciona los caracteres «para» solo si: – los siguientes caracteres no son «psicología» ó «normal» | El parapente El paraíso fiscal Fenómeno paranormal ❌ | 🔗 |
(?<=…) | Pasado positivo (Positive Lookbehind)
Solo encuentra patrones si existe una condición pasada. | /(?<=solu|informa)ción/g | Selecciona los caracteres «ción» solo si: – los caracteres anteriores son «solu» ó «informa» | Tengo la solución, con la información de la ecuación. ❌ | 🔗 |
(?<!…) | Pasado negativo (Negative Lookbehind)
Solo encuentra patrones si no existe una condición pasada. | /(?<!informa)ción/g | Selecciona los caracteres «ción» solo si: – los caracteres anteriores no son «informa» | La desilución y manipulación de la información | 🔗 |
Clases de caracteres
Limita los caracteres que estás buscando con las siguientes sintaxis:
Regexp | Descripción | Ejemplo | Explicación | Valores válidos | regex101 |
[…] | Delimitador de caracteres | /[aeiouáéíóú]/g | – Encuentra cualquiera de los caracteres especificados. | murciélago aburriendo bcdfghjklm ❌ | 🔗 |
[^…] | Excepción de caracteres | /[^aeiouáéíóú]/g | – Encuentra todos los caracteres excepto los especificados. | murciélago aburriendo bcdfghjklm | 🔗 |
[[:alnum:]] | Letras y dígitos | /[[:alnum:]]/g | – Encuentra todas letras y números comprendidos entre [A-Za-z0-9] | ¡¡¡Texto, 12345!!! | 🔗 |
[[:lower:]] | Caracteres en minúsculas | /[[:lower:]]/g | – Encuentra todos los caracteres en minúsculas | abcDEF | 🔗 |
[[:upper:]] | Caracteres en mayúsculas | /[[:upper:]]/g | – Encuentra todos los caracteres en mayúsculas | abcDEF | 🔗 |
Anclas
Las anclas sirven para indicar en qué parte del texto queremos aplicar el patrón de búsqueda. Veamos a continuación las sintaxis más utilizadas:
Regexp | Descripción | Ejemplo | Explicación | Valores válidos | regex101 |
^ | Busca el patrón de caracteres al comienzo de la cadena o al comienzo de cada línea, según el modificador global.
Recuerda que cuando se encuentra entre llaves significa lo contrario: [^entre llaves] | Sin modificador multilínea /^\w+/gCon modificador multilínea /^\w+/gm | – Busca el patrón al comienzo del texto. | Sin modificador multilínea: Soy un texto multilínea sin el modificador global «m»Con modificador multilínea: Soy un texto multilínea con el modificador global «m» | 🔗 |
$ | Busca el patrón de caracteres al final de la cadena o al final de cada línea, según el modificador global. | Sin modificador multilínea /\w+$/gCon modificador multilínea/Unicode /\w+$/gum | – Buscal el patrón al final del texto. | Este es el fin de la historia | 🔗 |
/A | Busca el patrón de caracteres siempre al comienzo del texto. No se ve afectado por el modificador global «m». | /\A\w+/gm | – A pesar de indicar el modificador «m» solo devolverá el conjunto de letras al principio del texto. | Solo afecta al comienzo aún con el modificador multilínea | 🔗 |
/Z | Busca el patrón de caracteres siempre al final del texto. No se ve afectado por el modificador global «m». | /\w+\Z/gm | – A pesar de indicar el modificador «m» solo devolverá el conjunto de letras al final del texto. | Siempre seleccionaré la última palabra | 🔗 |
Modificadores globales
Como verán en los ejemplos anteriores, todas las expresiones regulares las hemos encerrado con barras y una letra g al final (/…/g
). Esta sintaxis permite que podamos englobar la expresión y modificarla con distintos valores que veremos a continuación:
Modificador | Descripción | Ejemplo | Explicación | Valores válidos | regex101 |
/…/g | Global: busca todas las posibles coincidencias en el texto (no se detiene ante el primer hallazgo). | /(je|jé)/g | – Encuentra todos los caracteres «je» o «jé» en la cadena. | Aserejé, ja deje tejebe tude jebere Sebiunouba majabi an de bugui an de buididipí Aserejé, ja deje tejebe tude je. | 🔗 |
/…/m | Multilínea: busca el patrón en cada línea del texto. | /Fin de la cita.$/gm | – Encuentra la frase exacta «Fin de la cita.» al final de cada línea. | Yo presido. Fin de la cita. Y lo digo. Fin de la cita. | 🔗 |
/…/i | Insensitivo: busca el patrón en minúsculas o mayúsculas. | /a/gi | – Encuentra la letra «a» sea minúscula o mayúscula. | A de accesibilidad | 🔗 |
/…/u | Unicode: busca el patrón incluyendo caracteres de UTF-16. | /voc\w/gu | – Encuentra la frase «voc» seguida de cualquier caracter comprendido en UTF-16. | Assim você me mata | 🔗 |
Funciones PHP
Una vez que tengamos el patrón de caracteres a buscar, podremos especificar una serie de funciones de PHP:
preg_replace:
Esta función de PHP busca un patrón de caracteres en un texto y lo reemplaza por otro que le especifiquemos.
<?php
/**
* Mensaje que quiere evadir la política
* de comisiones de la plataforma.
*/
$mensaje = "Hola Juan: mi nombre es Mauricio y te dejo mi email para que
contactemos fuera de esta aplicación que cobra comisiones muy caras,
toma nota: mg@maugelves.com. Un saludo, Mauricio.";
/**
* Pero aquí viene la función justiciera.
*
* En PHP existe una función mejor para validar emails, pero
* usaremos funciones de expresiones regulares con
* fines didácticos.
* http://php.net/manual/en/filter.filters.php
*/
// Patrón para encontrar direcciones de email
$patron = "/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b/";
// Reemplazo cualquier email por el texto "correo eliminado"
$mensaje = preg_replace( $patron, "(correo eliminado)", $mensaje );
echo $mensaje;
/*
* Esto devuelve:
*
* Hola Juan: mi nombre es Mauricio y te dejo mi email para que
* contactemos fuera de esta aplicación que cobra comisiones muy caras,
* toma nota: (correo eliminado). Un saludo, Mauricio.
*
*/
preg_split:
Función ideal si queremos dividir un texto en un array por un patrón de texto. Veamos el siguiente ejemplo donde separamos un texto por espacios o comas.
<?php
/**
* Fragmento del Quijote de la Mancha
*/
$texto = "Y, viéndole don Quijote de aquella manera, con muestras de tanta
tristeza, le dijo: Sábete, Sancho, que no es un hombre más que
otro si no hace más que otro.";
// Patrón para encontrar espacios y comas (,).
$patron = "/[\s,]+/";
// Guardo en un array todas las palabras separadas por comas o espacios.
$array = preg_split( $patron, $texto );
var_dump( $array );
/*
* Esto devuelve:
*
* array(30) { [0]=> string(1) "Y" [1]=> string(9) "viéndole" [2]=> string(3) "don"
* [3]=> string(7) "Quijote" [4]=> string(2) "de" [5]=> string(7) "aquella"
* [6]=> string(6) "manera" [7]=> string(3) "con" [8]=> string(8) "muestras"
* [9]=> string(2) "de" [10]=> string(5) "tanta" [11]=> string(8) "tristeza"
* [12]=> string(2) "le" [13]=> string(5) "dijo:" [14]=> string(7) "Sábete"
* [15]=> string(6) "Sancho" [16]=> string(3) "que" [17]=> string(2) "no"
* [18]=> string(2) "es" [19]=> string(2) "un" [20]=> string(6) "hombre"
* [21]=> string(4) "más" [22]=> string(3) "que" [23]=> string(4) "otro"
* [24]=> string(2) "si" [25]=> string(2) "no" [26]=> string(4) "hace"
* [27]=> string(4) "más" [28]=> string(3) "que" [29]=> string(5) "otro." }
*
*/
preg_match:
Esta es tal vez la función más simple ya que devuelve un 1 si encuentra al menos un patrón de caracteres y un 0 en caso negativo o error. Vamos a definir un patrón para detectar si alguien escribe mal la palabra WordPress en un texto cualquiera (recuerden que lleva la letra W y P en mayúsculas).
<php
/**
* Un fragmento de texto con la palabra WordPress mal escrita
*/
$texto = "Hola, tengo un problema con mi página web. Está hecha
en wordpress y quería que alguien me eche una mano.
¿Qué debo hacer?"; // Parece gracioso pero suelo recibir emails de este tipo.
// Patrón para encontrar WordPress mal escritos.
$patron = "/(wordpress|wordPress)+/";
// Guardo en un array todas las palabras separadas por comas o espacios.
$hay_error = preg_match( $patron, $texto );
var_dump( $hay_error );
/*
* Esto devuelve:
*
* int(1)
*
*/
¿Cómo usarlo en WordPress? Plugin Moderdonizer

Luego de la chapa que solté con tanto tecnicismo es hora de ver cómo podemos implementar estas expresiones regulares en WordPress. Solo cambiará el entorno ya que seguiremos utilizando las mismas funciones nativas de PHP.
Voy a detallar un ejemplo con una linda locura que se nos ocurrió junto a Álvaro Gómez (AKA @Mrfoxtalbot).
Ambos somos fieles seguidores del programa de radio «La vida moderna«, una show humorístico donde a lo largo del tiempo han desarrollado un lenguaje propio. Por ejemplo, en lugar de decir «comedia» dicen «commedia» para identificar el tipo de humor que ellos realizan (que a veces roza límites muy arriesgados) y también reemplazan las terminaciones «ción/sión» por «ció/sió», haciedo alusión (y un poco de burla) al idioma catalán.
Con el juego de palabras se nos ocurrió que podíamos hacer un plugin (el cual está en fase de aprobación 😝) y subirlo al repositorio. La finalidad del mismo es simplemente reemplazar el título y contenido de cualquier entrada o página con las palabras típicas del programa. Para ello debíamos definir en primer lugar las reglas gramaticales, dos de ellas resultaron simples pero la doble «m» tenía un poco más de chicha: Este es el detalle de cada regla:
- Reemplazar palabras que acaben en «ción» por «ció» cuando después venga un espacio, punto, coma, interrogación o exclamación.
- Reemplazar palabras que acaben en «sión» por «sió» cuando después venga un espacio, punto, coma, interrogación o exclamación.
- Reemplazar la letra «m» por doble «mm» cuando la consonante se encuentre entre vocales.
Con las reglas definidas me puse manos a la obra y luego de varias correcciones di con las expresiones regulares correctas. Las mismas las utilizo con la función preg_replace()
de PHP cuando se ejecutan los filtros the_content
y the_title
.
El plugin, que de momento pueden encontrar en mi repositorio de Github, luce más o menos así:
<?php
/**
* Esta función reemplaza el contenido Godo con palabras de la República Dictatorial de Moderdonia.
* Estas son las reglas que se aplican:
*
* @author Mauricio Gelves
* @params $content string El contenido del post
* @returns string El contenido del post con las nuevas palabras moderdonizadas.
*/
function fn_modernonize( $content ) {
// Regla 1: "ción" por "ció" (ver comentarios en función)
$content = preg_replace('/ción(?=[ .!,?])/', 'ció', $content );
// Regla 2: "sión" por "sió" (ver comentarios en función)
$content = preg_replace('/sión(?=[ .!,?])/', 'sió', $content );
// Regla 3: "m" por "mm" (ver comentarios en función)
$content = preg_replace('/(?<=[aeiouáéíóú])m(?=[aeiouáéíóú])/', 'mm', $content );
return $content;
}
Conclusión
No me sorprenderé ni me avergonzaré cuando vuelva a mi propio artículo para saber cómo funcionan las expresiones regulares. Espero que vosotros también la dejéis apuntada como favorita para consultar en cualquier momento. Lo que sí puedo contarles es que escribiendo este artículo, que llevó muchas horas de desarrollo, me ha hecho conocer mucho más esta potente tecnología y sentirme más seguro de cara a futuras implementaciones. Es lo bueno de tener un blog.
Deja una respuesta