Expresiones regulares en PHP: las funciones preg_* usan el motor PCRE, el mismo estilo de patrones que casi todos los lenguajes. Lo propio de PHP está en los delimitadores, en el modificador u para el español y en cómo tratar el texto que escribe el usuario.
También te puede interesar
¿Coincide? preg_match
<?php
declare(strict_types=1);
$codigo = 'MX-2026-00418';
if (preg_match('/^([A-Z]{2})-(\d{4})-(\d{5})$/', $codigo, $m) === 1) {
echo "País: $m[1], año: $m[2], número: $m[3]\n";
}
preg_match('/^(?<pais>[A-Z]{2})-(?<anio>\d{4})-(?<num>\d{5})$/', $codigo, $m);
echo "País: {$m['pais']}, año: {$m['anio']}\n";
var_dump(preg_match('/^\d{5}$/', '1234'));salidaPaís: MX, año: 2026, número: 00418 País: MX, año: 2026 int(0)
En PHP las expresiones regulares van entre delimitadores, normalmente barras (/…/), y se escriben entre comillas simples para que PHP no interprete las barras invertidas. preg_match devuelve 1 si hay coincidencia y 0 si no, y deja los grupos en el array del tercer argumento. Con (?<nombre>…) los grupos tienen nombre, mucho más legible que $m[3]. Si quieres probarlas antes, tenemos un probador de expresiones regulares.
Todas las coincidencias: preg_match_all
<?php
declare(strict_types=1);
$texto = 'Escríbenos a ventas@ejemplo.com o a soporte@ejemplo.org antes del 31/12/2026.';
preg_match_all('/[\w.+-]+@[\w-]+\.[\w.]+/u', $texto, $m);
print_r($m[0]);
preg_match_all('/(\d{2})\/(\d{2})\/(\d{4})/', $texto, $m, PREG_SET_ORDER);
foreach ($m as [$todo, $dia, $mes, $anio]) {
echo "$todo → $anio-$mes-$dia\n";
}salidaArray
(
[0] => ventas@ejemplo.com
[1] => soporte@ejemplo.org
)
31/12/2026 → 2026-12-31Reemplazar: preg_replace y preg_replace_callback
<?php
declare(strict_types=1);
echo preg_replace('/\s+/', ' ', "demasiados espacios \n y saltos"), "\n";
echo preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', 'Entrega: 2026-10-27'), "\n";
$plantilla = 'Hola {nombre}, tu pedido {pedido} está listo.';
$datos = ['nombre' => 'Ana', 'pedido' => 'A-1042'];
echo preg_replace_callback('/\{(\w+)\}/', fn(array $m): string => $datos[$m[1]] ?? $m[0], $plantilla), "\n";salidademasiados espacios y saltos Entrega: 27/10/2026 Hola Ana, tu pedido A-1042 está listo.
En el reemplazo, $1, $2… son los grupos. Cuando el reemplazo depende de lo encontrado, preg_replace_callback llama a una función por cada coincidencia; aquí rellena una plantilla sencilla.
Tildes y eñes: el modificador u
<?php
declare(strict_types=1);
$nombre = 'Ñandú';
var_dump(preg_match('/^\w+$/', $nombre));
var_dump(preg_match('/^\w+$/u', $nombre));
var_dump(preg_match('/^.{5}$/', $nombre));
var_dump(preg_match('/^.{5}$/u', $nombre));
print_r(preg_split('//u', 'año', -1, PREG_SPLIT_NO_EMPTY));salidaint(0)
int(1)
int(0)
int(1)
Array
(
[0] => a
[1] => ñ
[2] => o
)Sin el modificador u, el motor de expresiones regulares trabaja con bytes, y la ñ o la ú (dos bytes cada una) no cuentan como letras ni como un solo carácter. Con u, entiende UTF-8. Ponlo siempre que el texto lo escriba una persona.
Lo que escribe el usuario: preg_quote
<?php
declare(strict_types=1);
$busqueda = 'C++ (2026)';
$texto = 'Curso de C++ (2026) y de C# (2026)';
var_dump(preg_match('/' . $busqueda . '/', $texto));
$patron = '/' . preg_quote($busqueda, '/') . '/u';
echo $patron, "\n";
var_dump(preg_match($patron, $texto));salidaint(0) /C\+\+ \(2026\)/u int(1)
Si una expresión regular incluye texto del usuario, sus +, paréntesis o puntos se interpretan como operadores: aquí C++ significa «una o más C» y los paréntesis forman un grupo, así que el patrón no encuentra el texto que está ahí mismo. Con otros textos podría no compilar o, peor, coincidir con lo que no debe. preg_quote los escapa, y su segundo argumento es el delimitador que usas. Para buscar un texto literal sin más, ni siquiera hace falta una expresión regular: str_contains es más rápido y no tiene trampas.
(a+)+, pueden tardar muchísimo con ciertos textos (se llama backtracking catastrófico). PHP corta la búsqueda al llegar a pcre.backtrack_limit y preg_match devuelve false: compara siempre con === 1 y revisa preg_last_error_msg() si algo no cuadra.Resumen
| Para | Usa |
|---|---|
| ¿Coincide? | preg_match($patron, $texto, $m) === 1 |
| Todas las coincidencias | preg_match_all (con PREG_SET_ORDER para iterar) |
| Reemplazar | preg_replace o preg_replace_callback |
| Partir un texto | preg_split |
| Texto en español | el modificador u |
| Texto del usuario dentro del patrón | preg_quote($texto, '/') |
Todo el código de esta página se ejecutó con PHP 8.5.12 en un contenedor limpio, sin acceso a la red, antes de publicarla; las salidas y los mensajes de error están copiados de esa ejecución.