Inicio / PHP / PHP Profesional: De Intermedio a Avanzado / Strings y Expresiones Regulares

Strings y Expresiones Regulares

mb_string, preg_match/replace/split, named groups, heredoc y funciones PHP 8.

Avanzado
🔒 Solo lectura
📖

Estás en modo lectura

Puedes leer toda la lección, pero para marcar progreso, hacer ejercicios y ganar XP necesitas una cuenta Pro.

Desbloquear por $9/mes

Strings y Expresiones Regulares en PHP

El manejo de cadenas de texto y expresiones regulares es fundamental en cualquier aplicación PHP. En esta lección aprenderás desde funciones multibyte hasta patrones avanzados de regex.


1. Funciones Multibyte (mb_string)

PHP maneja cadenas como secuencias de bytes. Para textos con caracteres especiales (ñ, á, ü, emojis), necesitas las funciones mb_*.

$texto = "Programación en español";

echo strlen($texto);      // 24 (bytes, ó ocupa 2 bytes)
echo mb_strlen($texto);   // 23 (caracteres reales)

Funciones esenciales

$frase = "Diseño técnico profesional";

// Convertir mayúsculas/minúsculas
echo mb_strtoupper($frase); // DISEÑO TÉCNICO PROFESIONAL
echo mb_strtolower($frase); // diseño técnico profesional

// Subcadena segura
echo mb_substr($frase, 0, 6); // Diseño

// Buscar posición
echo mb_strpos($frase, 'técnico'); // 7

// Detectar encoding
echo mb_detect_encoding($frase); // UTF-8

// Convertir encoding
$latin1 = mb_convert_encoding($frase, 'ISO-8859-1', 'UTF-8');

Tip: Configura el encoding por defecto en tu aplicación:

mb_internal_encoding('UTF-8');

2. preg_match: Buscar patrones

preg_match busca la primera coincidencia de un patrón regex.

$email = "usuario@ejemplo.com";

if (preg_match('/^[\w.+-]+@[\w-]+\.[\w.]+$/', $email)) {
    echo "Email válido";
}

Capturar grupos

$fecha = "2026-02-23";

preg_match('/(\d{4})-(\d{2})-(\d{2})/', $fecha, $matches);

echo $matches[0]; // 2026-02-23 (coincidencia completa)
echo $matches[1]; // 2026 (primer grupo)
echo $matches[2]; // 02
echo $matches[3]; // 23

Grupos nombrados

$log = "[2026-02-23 14:30:00] ERROR: Conexión fallida";

$patron = '/\[(?P<fecha>[\d-]+)\s(?P<hora>[\d:]+)\]\s(?P<nivel>\w+):\s(?P<mensaje>.+)/';

if (preg_match($patron, $log, $matches)) {
    echo $matches['fecha'];   // 2026-02-23
    echo $matches['nivel'];   // ERROR
    echo $matches['mensaje']; // Conexión fallida
}

preg_match_all: Todas las coincidencias

$html = '<a href="https://php.net">PHP</a> y <a href="https://laravel.com">Laravel</a>';

preg_match_all('/href="([^"]+)"/', $html, $matches);

print_r($matches[1]);
// ['https://php.net', 'https://laravel.com']

3. preg_replace: Reemplazar con regex

$texto = "Mi teléfono es 55-1234-5678 o 33-9876-5432";

// Ocultar números telefónicos
$censurado = preg_replace('/\d{2}-\d{4}-\d{4}/', '**-****-****', $texto);
echo $censurado; // Mi teléfono es **-****-**** o **-****-****

Usar referencias en el reemplazo

$texto = "Juan García y María López";

// Invertir nombre y apellido
$invertido = preg_replace('/(\w+)\s(\w+)/', '$2, $1', $texto);
echo $invertido; // García, Juan y López, María

preg_replace_callback: Reemplazo dinámico

$plantilla = "Hola {nombre}, tu saldo es {saldo}";

$datos = ['nombre' => 'Ana', 'saldo' => '$1,500'];

$resultado = preg_replace_callback('/\{(\w+)\}/', function ($m) use ($datos) {
    return $datos[$m[1]] ?? $m[0];
}, $plantilla);

echo $resultado; // Hola Ana, tu saldo es $1,500

4. preg_split: Dividir con regex

// Dividir por múltiples separadores
$texto = "PHP,JavaScript;Python|Ruby";

$lenguajes = preg_split('/[,;|]/', $texto);
// ['PHP', 'JavaScript', 'Python', 'Ruby']

// Dividir por uno o más espacios
$linea = "campo1   campo2     campo3";
$campos = preg_split('/\s+/', $linea);
// ['campo1', 'campo2', 'campo3']

5. Lookahead y Lookbehind

Permiten verificar qué hay antes o después de una posición sin incluirlo en la coincidencia.

Lookahead positivo (?=...)

// Encontrar palabras seguidas de un número
$texto = "item1 nombre item2 descripción item3";

preg_match_all('/\w+(?=\d)/', $texto, $matches);
// ['item', 'item', 'item']

Lookbehind positivo (?<=...)

// Extraer montos después del signo $
$texto = "Precio: $450 y descuento: $50";

preg_match_all('/(?<=\$)\d+/', $texto, $matches);
// ['450', '50']

Lookahead negativo (?!...) y Lookbehind negativo (?<!...)

// Palabras que NO terminan en "s"
preg_match_all('/\b\w+\b(?!s)/', "gatos perro casas libro", $matches);

// Números que NO están precedidos por $
preg_match_all('/(?<!\$)\b\d+\b/', "precio $100 cantidad 5", $matches);
// ['5']

6. Heredoc y Nowdoc

Heredoc — Permite interpolación de variables

$nombre = "Carlos";
$lenguaje = "PHP";

$mensaje = <<<EOT
Hola $nombre,

Bienvenido al curso de $lenguaje.
Este texto mantiene los saltos de línea
y permite usar "comillas" sin escapar.
EOT;

echo $mensaje;

Nowdoc — Sin interpolación (como comillas simples)

$raw = <<<'EOT'
Esto es texto literal.
Las variables como $nombre NO se interpretan.
Ideal para plantillas o código fuente.
EOT;

Tip: Desde PHP 7.3, el cierre puede estar indentado:

$html = <<<HTML
    <div>
        <p>Contenido</p>
    </div>
    HTML;

7. sprintf: Formateo de cadenas

sprintf permite crear cadenas con formato controlado.

// Formato numérico
$precio = 1234.5;
echo sprintf("Precio: $%,.2f", $precio);
// Precio: $1,234.50

// Padding con ceros
$orden = 42;
echo sprintf("ORD-%05d", $orden);
// ORD-00042

// Múltiples valores
echo sprintf("%s tiene %d años y mide %.1f m", "Ana", 25, 1.65);
// Ana tiene 25 años y mide 1.7 m

Especificadores comunes

Especificador Tipo Ejemplo
%s String "hola"
%d Entero 42
%f Float 3.140000
%.2f Float 2 decimales 3.14
%05d Entero con padding 00042
%x Hexadecimal 2a
// Generar colores hex
$r = 255; $g = 128; $b = 0;
echo sprintf('#%02x%02x%02x', $r, $g, $b); // #ff8000

8. Funciones de PHP 8: str_contains, str_starts_with, str_ends_with

Antes de PHP 8, verificar subcadenas requería funciones complicadas o propensas a errores:

// Antes (PHP < 8) — propenso a bugs con strpos
if (strpos($url, 'https') !== false) { /* ... */ }

// Ahora (PHP 8+) — claro y legible
if (str_contains($url, 'https')) { /* ... */ }

str_starts_with y str_ends_with

$archivo = "documento.pdf";

if (str_ends_with($archivo, '.pdf')) {
    echo "Es un PDF";
}

$ruta = "/api/v2/usuarios";

if (str_starts_with($ruta, '/api/')) {
    echo "Es una ruta de API";
}

Comparación con regex

// Regex (más potente pero más lento)
if (preg_match('/\.pdf$/i', $archivo)) { /* ... */ }

// str_ends_with (más rápido para casos simples)
if (str_ends_with(strtolower($archivo), '.pdf')) { /* ... */ }

Regla práctica: Usa las funciones str_* para verificaciones simples y regex para patrones complejos.


9. Otras funciones útiles de strings

// Repetir cadena
echo str_repeat('=-', 20); // =-=-=-=-=-=-...

// Rellenar cadena
echo str_pad('42', 6, '0', STR_PAD_LEFT); // 000042

// Dividir en array
$csv = "uno,dos,tres";
$partes = explode(',', $csv); // ['uno', 'dos', 'tres']

// Unir array en string
echo implode(' | ', $partes); // uno | dos | tres

// Recortar espacios
echo trim("  hola  ");   // "hola"
echo ltrim("  hola  ");  // "hola  "
echo rtrim("  hola  ");  // "  hola"

// Reemplazar (sin regex, más rápido)
echo str_replace('mundo', 'PHP', 'Hola mundo'); // Hola PHP

10. Ejemplo práctico: Validador de contraseña

function validarPassword(string $password): array {
    $errores = [];

    if (mb_strlen($password) < 8) {
        $errores[] = 'Mínimo 8 caracteres';
    }
    if (!preg_match('/[A-Z]/', $password)) {
        $errores[] = 'Debe contener al menos una mayúscula';
    }
    if (!preg_match('/[a-z]/', $password)) {
        $errores[] = 'Debe contener al menos una minúscula';
    }
    if (!preg_match('/\d/', $password)) {
        $errores[] = 'Debe contener al menos un número';
    }
    if (!preg_match('/[!@#$%^&*()_+\-=\[\]{}|;:,.<>?]/', $password)) {
        $errores[] = 'Debe contener al menos un carácter especial';
    }

    return $errores;
}

$errores = validarPassword('MiClave123!');
if (empty($errores)) {
    echo "Contraseña válida";
} else {
    echo "Errores:\n" . implode("\n", $errores);
}

Resumen

Función / Concepto Uso
mb_strlen, mb_substr Manejo seguro de UTF-8
preg_match Buscar patrón regex
preg_replace Reemplazar con regex
preg_split Dividir con regex
Lookahead / Lookbehind Verificar contexto sin capturar
Heredoc / Nowdoc Strings multilínea
sprintf Formateo de cadenas
str_contains (PHP 8) Verificar subcadena
str_starts_with / str_ends_with Verificar inicio/final

Combinar estas herramientas te permite manipular texto de forma profesional y segura en cualquier aplicación PHP.

🔒

Ejercicio práctico disponible

Procesador de texto con regex

Desbloquear ejercicios
// Procesador de texto con regex
// Desbloquea Pro para acceder a este ejercicio
// y ganar +50 XP al completarlo

function ejemplo() {
    // Tu código aquí...
}

¿Te gustó esta lección?

Con Pro puedes marcar progreso, hacer ejercicios, tomar quizzes, ganar XP y obtener tu constancia.

Ver planes desde $9/mes