Expresiones Regulares en PHP
Aprende a usar expresiones regulares en PHP con las funciones preg_ para validar, extraer y reemplazar texto mediante patrones.
Una expresión regular (regex) es un patrón que describe un conjunto de cadenas. En lugar de buscar un fragmento de texto fijo, describes su forma — "una dirección de correo electrónico", "una secuencia de dígitos", "una palabra que termina en .php" — y PHP encuentra, valida, reemplaza o divide texto que coincida.
Este capítulo explica cómo funcionan las funciones preg_ de PHP, la sintaxis de un patrón (delimitadores, clases de caracteres, cuantificadores, grupos, anclas) y las tareas prácticas más habituales: validar entradas, extraer datos y reemplazar texto.
Qué son las expresiones regulares
Una expresión regular es una secuencia de caracteres que define un patrón de búsqueda. La mayoría de los caracteres se corresponden consigo mismos — el patrón cat coincide con el texto literal cat. El poder proviene de los metacaracteres, que representan categorías de caracteres o repeticiones:
| Token | Significado | Ejemplo de coincidencia |
|---|---|---|
. | Cualquier carácter individual (excepto salto de línea) | c.t → cat, cut |
\d | Un dígito 0-9 | \d\d → 42 |
\w | Un carácter "de palabra" (a-z, A-Z, 0-9, _) | \w+ → hello_1 |
\s | Espacio en blanco (espacio, tabulación, salto de línea) | — |
[abc] | Cualquiera de a, b, c | [aeiou] → e |
[^abc] | Cualquier carácter excepto a, b, c | — |
a* | Cero o más a | "", aaa |
a+ | Una o más a | a, aaa |
a? | Cero o una a (opcional) | "", a |
a{2,4} | Entre 2 y 4 de a | aa, aaaa |
^ / $ | Inicio / fin de la cadena | — |
| | Alternancia ("o") | cat|dog → cat o dog |
() | Agrupación / captura | (ab)+ → abab |
Cómo funcionan las expresiones regulares en PHP
PHP utiliza PCRE (Expresiones Regulares Compatible con Perl) a través de la familia de funciones preg_. Las más utilizadas son:
| Función | Qué hace |
|---|---|
preg_match() | Comprueba si un patrón coincide; captura la primera coincidencia |
preg_match_all() | Encuentra todas las coincidencias en una cadena |
preg_replace() | Reemplaza cada coincidencia con nuevo texto |
preg_split() | Divide una cadena según un patrón |
preg_quote() | Escapa los metacaracteres de regex en una cadena literal |
La sintaxis de un patrón PHP
Un patrón PHP es una cadena compuesta de tres partes: un delimitador, el patrón y modificadores opcionales.
/pattern/modifiersEl primer carácter es el delimitador — casi siempre /, pero cualquier carácter no alfanumérico funciona (#, ~, !). Elegir un delimitador que no aparezca en el patrón evita tener que escaparlo. Por ejemplo, hacer coincidir una ruta URL es más limpio con #:
"#^/users/\d+$#" // no need to escape the slashesLos modifiers son letras opcionales tras el delimitador de cierre que cambian el comportamiento del motor:
i— insensible a mayúsculas:/php/icoincide conPHP,Php,php.m— multilínea:^y$coinciden al inicio/fin de cada línea, no solo de toda la cadena.s— single line ("dotall"):.también coincide con saltos de línea.u— trata el patrón y el texto como UTF-8. Úsalo con cualquier texto que contenga caracteres no ASCII.x— extendido: los espacios en blanco del patrón se ignoran, permitiendo espaciar y comentar patrones complejos.
Comprobar una coincidencia con preg_match
preg_match() devuelve 1 si el patrón se encuentra, 0 si no, y false en caso de error. Es la opción adecuada para una pregunta de sí/no como "¿contiene esta cadena un dígito?"
El tercer argumento opcional, $matches, se rellena con los resultados: $matches[0] es la coincidencia completa, y $matches[1], $matches[2], … son los grupos de captura en orden — las subcadenas capturadas por cada par de paréntesis.
Validar la entrada del usuario
Un uso habitual de las regex es validar la entrada del usuario — comprobar que un valor tiene la forma correcta antes de almacenarlo o confiar en él. Aquí tienes una comprobación básica de correo electrónico:
<?php
$email = "[email protected]";
if (preg_match("/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/", $email)) {
echo "Valid email address";
} else {
echo "Invalid email address";
}
?>Las anclas ^ y $ son importantes aquí: sin ellas, el patrón coincidiría con un correo electrónico dentro de una cadena más grande, por lo que "junk [email protected] junk" pasaría la validación. Con ellas, toda la cadena debe ser un único correo electrónico.
Para el correo electrónico específicamente, el filter_var() integrado de PHP con FILTER_VALIDATE_EMAIL es más robusto que una regex escrita a mano. Recurre a las regex cuando necesites un formato que los filtros no cubran — códigos postales, IDs personalizados, formatos de teléfono. Consulta la validación de formularios PHP para ver un ejemplo completo de comprobación de entradas.
Encontrar todas las coincidencias con preg_match_all
Mientras que preg_match() se detiene en la primera coincidencia, preg_match_all() las recopila todas — útil para extraer cada hashtag, precio o enlace de un bloque de texto.
<?php
$text = "Prices: $12, $7 and $349";
preg_match_all("/\\\$(\d+)/", $text, $matches);
print_r($matches[1]); // the captured numbers
?>$matches[1] contiene un array con cada grupo capturado — en este caso, ["12", "7", "349"].
Reemplazar texto con preg_replace
preg_replace() sustituye cada coincidencia. En la cadena de reemplazo, $1, $2, … hacen referencia a los grupos capturados, por lo que puedes reescribir además de eliminar:
<?php
$date = "2026-06-21";
// Reformat YYYY-MM-DD into DD/MM/YYYY
echo preg_replace("/(\d{4})-(\d{2})-(\d{2})/", "$3/$2/$1", $date);
// 21/06/2026
?>Para dividir una cadena en partes según un patrón en lugar de reemplazarlo, usa preg_split() — por ejemplo, dividir en cualquier secuencia de espacios en blanco con /\s+/.
Técnicas avanzadas
Una vez que te sientas cómodo con los conceptos básicos, estas funcionalidades permiten manejar patrones más complejos:
- Grupos de captura
(...)— extrae partes específicas de una coincidencia, como se mostró anteriormente con$matches[1]. - Grupos de no captura
(?:...)— agrupa sin ocupar una posición en$matches, cuando solo necesitas la agrupación para un cuantificador o alternancia. - Grupos con nombre
(?<year>\d{4})— referencia una coincidencia por nombre ($matches['year']) en lugar de por número. - Lookahead
(?=...)y lookbehind(?<=...)— coincide según lo que viene después o antes, sin consumirlo. Útil para "un número seguido depx" sin capturarpx. - Cuantificadores perezosos
*?,+?— coincide con el menor número posible de caracteres. Por defecto,.*es codicioso y captura todo lo que puede.
Una nota sobre el escape: caracteres como ., +, *, ?, (, ), [, \ tienen un significado especial. Para que coincidan literalmente, prefíjalos con una barra invertida (\. coincide con un punto literal). Cuando el texto literal proviene de una variable, usa preg_quote() para escaparlo de forma segura.
Errores comunes
- Olvidar los delimitadores. Los patrones PHP son cadenas y deben incluir delimitadores:
"/\d+/", no"\d+". Omitirlos genera un aviso y la coincidencia falla. - Doble escape en cadenas entre comillas dobles. Dentro de
"...", una barra invertida es también un escape de PHP."/\d/"funciona porque\dno es un escape de PHP, pero para coincidir con un$literal necesitas"/\\$/". Las cadenas entre comillas simples ('/\d/') evitan esta sorpresa. - La coincidencia codiciosa captura demasiado.
<.*>sobre<a><b>coincide con todo<a><b>, no solo con<a>. Usa un patrón perezoso<.*?>o una clase negada<[^>]*>. - Omitir el modificador
uen UTF-8. Sin/u,.y\woperan sobre bytes, corrompiendo los caracteres multibyte.
Conclusión
Las expresiones regulares permiten describir la forma del texto en lugar de su contenido exacto, lo que las hace indispensables para validar entradas, extraer datos y transformar cadenas. En PHP las utilizas a través de las funciones preg_: preg_match() y preg_match_all() para buscar, preg_replace() para reescribir y preg_split() para dividir cadenas. Comienza con anclas, clases de caracteres y cuantificadores, y luego añade grupos y lookarounds a medida que tus patrones crezcan. Para profundizar en las cadenas con las que trabajarás, consulta PHP Strings.