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");
}
?>