preg_match() y preg_match_all() en PHP: buscar patrones con expresiones regulares

Las expresiones regulares en PHP se articulan principalmente a través de dos funciones: preg_match() para comprobar si un patrón existe y capturar grupos, y preg_match_all() para encontrar todas las coincidencias de un patrón en una cadena. Ambas usan el motor PCRE (Perl Compatible Regular Expressions).

preg_match(): primera coincidencia

preg_match(string $pattern, string $subject, array &$matches = []) devuelve 1 si hay coincidencia, 0 si no la hay, y false si hay un error en el patrón:

<?php
// El patrón va entre delimitadores (/ es el más habitual)
$email = '[email protected]';
$resultado = preg_match('/^[w.+-]+@[w-]+.[a-z]{2,}$/i', $email);
var_dump($resultado); // int(1)

// Comprobar: usar === para distinguir false de 0
$resultado = preg_match('/^d{5}$/', '28001');
if ($resultado === false) {
    echo 'Error en el patrón';
} elseif ($resultado === 0) {
    echo 'Sin coincidencia';
} else {
    echo 'Coincidencia encontrada';
}
?>

Grupos de captura numerados

Los paréntesis crean grupos de captura. El índice 0 de $matches contiene la coincidencia completa, y desde el índice 1 en adelante los grupos capturados:

<?php
$fecha = '2026-07-22';
preg_match('/^(d{4})-(d{2})-(d{2})$/', $fecha, $matches);

echo $matches[0]; // 2026-07-22  (coincidencia completa)
echo $matches[1]; // 2026        (grupo 1: año)
echo $matches[2]; // 07          (grupo 2: mes)
echo $matches[3]; // 22          (grupo 3: día)
?>

Grupos de captura con nombre

La sintaxis (?P<nombre>...) da nombre a los grupos, haciendo el código más legible:

<?php
$url = 'https://programacion.net/articulo/php-arrays_3500';
preg_match('/^(?P<scheme>https?)://(?P<host>[w.]+)/(?P<path>.*)$/', $url, $m);

echo $m['scheme']; // https
echo $m['host'];   // programacion.net
echo $m['path'];   // articulo/php-arrays_3500

// También accesibles por posición
echo $m[1]; // https
echo $m[2]; // programacion.net
?>

Modificadores más usados

  • i — insensible a mayúsculas/minúsculas
  • m — multilínea: ^ y $ coinciden con inicio/fin de cada línea
  • s — single-line: el punto . también coincide con saltos de línea
  • u — modo Unicode: el patrón y el sujeto se tratan como UTF-8
  • x — extended: permite espacios y comentarios en el patrón
<?php
// i: case-insensitive
preg_match('/^php$/i', 'PHP');     // 1
preg_match('/^php$/i', 'Php');     // 1

// m: multiline
$texto = "línea 1nlínea 2nlínea 3";
preg_match_all('/^línea/m', $texto, $m);
echo count($m[0]); // 3 ? coincide en cada línea

// s: el punto incluye n
preg_match('/

.*?/s', '<p>textonen dos líneas</p>', $m); // u: UTF-8 preg_match('/^w+$/u', 'café'); // 1 (con 'u'; sin él, 'é' rompe w) ?>

preg_match_all(): todas las coincidencias

<?php
$html = '<a href="https://php.net">PHP</a> y <a href="https://python.org">Python</a>';
preg_match_all('/href="([^"]+)"/', $html, $coincidencias);

// $coincidencias[0]: array de coincidencias completas
// $coincidencias[1]: array de grupos 1
print_r($coincidencias[1]);
// ['https://php.net', 'https://python.org']
?>

PREG_SET_ORDER vs PREG_PATTERN_ORDER

<?php
$texto = 'precio: 12.50, peso: 3.75, stock: 100';
preg_match_all('/(w+): ([d.]+)/', $texto, $m);

// PREG_PATTERN_ORDER (por defecto): primero todas las coincidencias completas, luego grupos
// $m[0] = ['precio: 12.50', 'peso: 3.75', 'stock: 100']
// $m[1] = ['precio', 'peso', 'stock']
// $m[2] = ['12.50', '3.75', '100']

preg_match_all('/(w+): ([d.]+)/', $texto, $m, PREG_SET_ORDER);
// PREG_SET_ORDER: agrupa por coincidencia
// $m[0] = ['precio: 12.50', 'precio', '12.50']
// $m[1] = ['peso: 3.75',    'peso',   '3.75']
// $m[2] = ['stock: 100',    'stock',  '100']
foreach ($m as $item) {
    echo $item[1] . ' = ' . $item[2] . "n";
}
?>

El error típico: confundir false con 0

<?php
// MAL: este if pasa tanto cuando no hay coincidencia (0) como cuando hay error (false)
if (!preg_match($patron, $sujeto)) {
    echo 'sin resultado';
}

// BIEN: distinguir los tres casos
$r = preg_match($patron, $sujeto, $m);
if ($r === false) {
    throw new RuntimeException('Error en el patrón regex: ' . preg_last_error_msg());
} elseif ($r === 0) {
    echo 'Sin coincidencia';
} else {
    echo 'Encontrado: ' . $m[0];
}
?>

La documentación de preg_match() y la de preg_match_all() incluyen la referencia completa de los flags y los modificadores de patrón.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP