Rangos, Atajos y Agrupadores en Expresiones Regulares
En esta lección aprenderás a usar los rangos ([]
),
atajos (\d
, \w
, \s
) y
agrupadores (()
, |
) para crear patrones potentes
y reutilizables. Usaremos ejemplos prácticos con preg_match()
y
preg_replace()
en PHP.
Metacaracteres de Rango ([]
)
Los corchetes []
especifican un conjunto de caracteres
válidos. Basta con que uno esté presente para que haya coincidencia.
[abc]
: Coincide con “a”, “b”, o “c”.[a-c]
: Coincide con cualquier letra de “a” a “c”.[^abc]
: Coincide con cualquier carácter excepto “a”, “b”, o “c”.[0-9]
: Cualquier dígito.[A-Za-z]
: Cualquier letra.
Ejemplo:
<?php
declare(strict_types=1);
$texto = "el ala aleve del leve abanico";
$patron = "/[aeiou]/"; // Cualquier vocal
// Coincide: "a", "e", "i", "o", "u" (por ejemplo, "a" en "ala").
// No coincide: Consonantes o caracteres no alfabéticos.
$string = preg_replace($patron, "<b>\\0</b>", $texto);
echo "$string\n";
$patron = "/[^aeiou]/"; // Cualquier no vocal
// Coincide: Consonantes, espacios, etc. (por ejemplo, "l" en "el").
// No coincide: "a", "e", "i", "o", "u".
$string = preg_replace($patron, "<b>\\0</b>", $texto);
echo "$string\n";
?>
Notas: - Dentro de []
, ^
significa negación, no ancla. - Solo escapa ]
,
\
, ^
, y -
dentro de
[]
; otros metacaracteres son literales.
Atajos
Los rangos comunes tienen atajos:
\d
:[0-9]
(dígitos).\D
:[^0-9]
(no dígitos).\w
:[A-Za-z0-9_]
(letras, dígitos, guion bajo).\W
:[^A-Za-z0-9_]
(no alfanuméricos).\s
:[ \t\n\r]
(espacios en blanco).\S
:[^ \t\n\r]
(no espacios).
Ejemplo:
<?php
declare(strict_types=1);
$texto = "el ala aleve del leve abanico";
$patron = "/\w\s/"; // Letra seguida de espacio
// Coincide: "l " (en "el "), "e " (en "aleve ").
// no coincide: Letras sin espacio o espacios solos.
$string = preg_replace($patron, "<b>\\0</b>", $texto);
echo "$string\n";
?>
Nota: Evita atajos POSIX ([[:alpha:]]
)
en PHP; usa PCRE para mayor compatibilidad.
Metacaracteres de Alternancia y Agrupadores
- Paréntesis (
()
): Agrupan caracteres para aplicar cuantificadores o capturar subpatrones. - Alternancia (
|
): Coincide con una u otra opción.
Ejemplo: Agrupación:
<?php
declare(strict_types=1);
$texto = "el ala aleve del leve abanico";
$patron = "/(al)/"; // Captura "al"
// Coincide: "al" (en "ala", "aleve").
// No coincide: "a" o "l" solos.
$string = preg_replace($patron, "<b>\\1</b>", $texto);
echo "$string\n";
?>
Este patrón captura el fragmento "al" en un grupo, que luego se referencia con \1
en la cadena de reemplazo. Esto permite resaltar solo el texto coincidente.
Ejemplo: Alternancia:
<?php
declare(strict_types=1);
$texto = "Don Juan o Doña Ana";
$patron = "/(Don|Doña)/";
// Coincide: "Don" o "Doña" (por ejemplo, "Don Juan").
// No coincide: "Sr", "Dña".
$string = preg_replace($patron, "<b>\\1</b>", $texto);
echo "$string\n";
?>
Es buena práctica agrupar las opciones con paréntesis al usar |
para controlar bien la prioridad.
Capturas y Retroreferencias
Los paréntesis capturan subpatrones, accesibles con \1
,
\2
, etc. La captura \0
es el patrón
completo.
Ejemplo: URLs:
<?php
declare(strict_types=1);
$texto = "Visita http://www.ignit.net";
$patron = "/http:\/\/([a-zA-Z0-9.]+\.(com|net|org))/";
// Coincide: URLs como "http://www.ignit.net".
// No coincide: "ftp://", dominios sin ".com/.net/.org".
$string = preg_replace($patron, "<a href=\"\\0\">\\1</a>", $texto);
echo "$string\n";
?>
Sin captura:
<?php
declare(strict_types=1);
$patron = "/http:\/\/([a-zA-Z0-9.]+\.(?:com|net|org))/"; // ?: evita captura
// Coincide: Igual que arriba, pero no captura ".com/.net/.org".
// No coincide: Igual que arriba.
$string = preg_replace($patron, "<a href=\"\\0\">\\1</a>", $texto);
echo "$string\n";
?>
Recuerda, \0
se refiere a la coincidencia completa, mientras que \1
, \2
... se refieren a cada grupo capturado en orden
Notas: - Las capturas consumen recursos; usa
(?:...)
para agrupar sin capturar. - PHP soporta hasta 99
retroreferencias capturadas.
Seguridad
- Sanitización: Escapa patrones de usuario con
preg_quote()
:
<?php
declare(strict_types=1);
$entrada = filter_input(INPUT_POST, "patron", FILTER_SANITIZE_STRING) ?? "";
$patron = "/" . preg_quote($entrada, "/") . "/";
// Coincide: La entrada sanitizada como literal.
// No coincide: Entradas maliciosas no escapadas.
$texto = "Prueba segura";
preg_match($patron, $texto);
?>
- Validación: Limita la longitud de entradas para evitar patrones maliciosos:
<?php
if (strlen($entrada) > 50) {
exit("Patrón demasiado largo");
}
?>