preg_match_all()
En PHP, preg_match_all() realiza una búsqueda global con expresiones regulares y devuelve todas las coincidencias encontradas en una cadena.
Introducción
En PHP, las expresiones regulares son esenciales para buscar y manipular cadenas. Mientras que preg_match() se detiene en la primera coincidencia, preg_match_all() continúa analizando y devuelve cada ocurrencia de un patrón en una cadena. Úsala cuando necesites extraer todos los números de teléfono, todas las etiquetas, todas las palabras o cualquier estructura repetitiva de un texto.
Este artículo explica la sintaxis, el importante argumento $flags que controla cómo se organizan los resultados, y varios ejemplos prácticos.
Sintaxis
preg_match_all(
string $pattern,
string $subject,
array &$matches = null,
int $flags = PREG_PATTERN_ORDER,
int $offset = 0
): int|false$pattern— la expresión regular, delimitada por/.../(o cualquier par de delimitadores coincidentes).$subject— la cadena en la que buscar.$matches— un array de salida (pasado por referencia) que se rellena con todas las coincidencias encontradas.$flags— opcional. Controla cómo se estructura$matches(ver más abajo).$offset— opcional. Desplazamiento en bytes dentro de$subjectdesde el cual comenzar la búsqueda.
Devuelve el número de coincidencias completas del patrón (que puede ser 0), o false si el patrón no es válido.
Una coincidencia simple
El uso más básico es recopilar cada subcadena que coincida con un patrón. Aquí extraemos todos los números de una oración:
<?php
$subject = 'Room 12, floor 3, building 7';
$count = preg_match_all('/\d+/', $subject, $matches);
echo "Found $count numbers\n";
print_r($matches[0]);Salida:
Found 3 numbers
Array
(
[0] => 12
[1] => 3
[2] => 7
)Cuando el patrón no tiene grupos de captura, $matches[0] contiene la lista de coincidencias completas.
Elegir un indicador: PREG_PATTERN_ORDER vs PREG_SET_ORDER
El argumento $flags decide cómo se organizan las coincidencias y los grupos de captura. Los dos indicadores principales son mutuamente excluyentes:
PREG_PATTERN_ORDER(el valor predeterminado) —$matches[0]contiene todas las coincidencias completas,$matches[1]contiene todas las capturas del grupo 1,$matches[2]contiene todas las capturas del grupo 2, y así sucesivamente. Piénsalo como "columna por columna".PREG_SET_ORDER—$matches[0]es la primera coincidencia completa (coincidencia completa + sus grupos),$matches[1]es la segunda, y así sucesivamente. Piénsalo como "fila por fila".
También puedes añadir PREG_OFFSET_CAPTURE para registrar el desplazamiento en bytes de cada coincidencia junto a su texto.
PREG_SET_ORDER (agrupar resultados por ocurrencia)
Esta disposición es la más fácil de recorrer en bucle cuando cada coincidencia tiene varios grupos de captura:
Salida:
Name: Alice, Age: 25
Name: Bob, Age: 30Con PREG_SET_ORDER, cada $match es una ocurrencia: $match[0] es la coincidencia completa, $match[1] es el primer grupo (nombre), $match[2] es el segundo grupo (edad).
PREG_PATTERN_ORDER (agrupar resultados por patrón)
El mismo patrón con el indicador predeterminado devuelve los grupos como arrays paralelos:
<?php
$pattern = '/([A-Z][a-z]+) (\d+)/';
$subject = 'Alice 25 Bob 30';
preg_match_all($pattern, $subject, $matches, PREG_PATTERN_ORDER);
print_r($matches[1]); // all names
print_r($matches[2]); // all agesSalida:
Array
(
[0] => Alice
[1] => Bob
)
Array
(
[0] => 25
[1] => 30
)Grupos de captura con nombre
Nombrar los grupos con (?<nombre>...) hace que el resultado sea autodocumentado — los nombres se convierten en claves del array (junto con los índices numéricos):
<?php
$pattern = '/(?<name>[A-Z][a-z]+) (?<age>\d+)/';
$subject = 'Alice 25 Bob 30';
preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
echo "{$match['name']} is {$match['age']}\n";
}Salida:
Alice is 25
Bob is 30Errores comunes
- Verifica el valor de retorno, no el array. Un patrón puede no tener coincidencias y aun así ejecutarse correctamente;
preg_match_all()devuelve0, mientras quefalseindica que la expresión regular no es válida. Usa=== falsepara detectar errores. Consultapreg_last_error()para conocer el motivo específico del fallo. $matchesse sobreescribe. Cada llamada reemplaza el contenido anterior del array de salida.- Elige el indicador adecuado para tu bucle. Usa
PREG_SET_ORDERcuando quieras una fila por coincidencia; usa el valor predeterminadoPREG_PATTERN_ORDERcuando quieras una columna por grupo. - Escapa los caracteres especiales en patrones dinámicos con
preg_quote()cuando el patrón proviene de la entrada del usuario.
Conclusión
preg_match_all() devuelve todas las coincidencias de un patrón en una cadena, convirtiéndola en la función ideal para extraer datos repetitivos. La clave para usarla correctamente es comprender el argumento $flags: PREG_SET_ORDER agrupa los resultados por ocurrencia, mientras que el valor predeterminado PREG_PATTERN_ORDER los agrupa por grupo de captura.
Para herramientas relacionadas, consulta preg_match() para una sola coincidencia, preg_replace() para buscar y reemplazar, y preg_split() para dividir cadenas por un patrón.