HOWTO · C

Expresiones Regulares en C

En este artículo, hablaremos sobre las expresiones regulares en C.

En esta página

Las funciones de expresiones regulares de POSIX permiten que un programa en C compile un patrón, pruebe cadenas y compruebe si cada prueba encontró una coincidencia. Las expresiones regulares no forman parte del lenguaje C; este artículo utiliza la interfaz POSIX <regex.h>.

Expresiones regulares en C con POSIX

Una expresión regular describe un patrón de texto. POSIX ofrece dos sintaxis principales para los patrones: las expresiones regulares básicas y las extendidas. En los ejemplos siguientes se selecciona la sintaxis extendida con REG_EXTENDED.

Las expresiones entre corchetes permiten encontrar un carácter de un conjunto. Por ejemplo, [abc] coincide con a, b o c; [[:digit:]] coincide con un dígito; [[:alnum:]_] coincide con un carácter alfanumérico o un guion bajo; y [[:lower:]] coincide con una letra minúscula según la configuración regional activa. Una clase de caracteres POSIX debe escribirse dentro de una expresión entre corchetes, por lo que formas como [:number:] y [:word:] no son clases estándar. Use [[:digit:]] para los dígitos y [[:alnum:]_] si necesita letras, dígitos y guion bajo.

El comportamiento de las coincidencias puede depender de la configuración regional actual, especialmente en las clases de caracteres y al ignorar mayúsculas y minúsculas. Configure la región de forma deliberada si la aplicación necesita reglas específicas. Las implementaciones de POSIX proporcionan esta API, pero el lenguaje C por sí solo no la garantiza.

Compilar una expresión regular POSIX con regcomp()

Declare un objeto regex_t para almacenar la expresión compilada y pase a regcomp() su dirección, un patrón terminado en NUL y las opciones de compilación. Con REG_EXTENDED, operadores como + usan la sintaxis de expresiones regulares extendidas. Añada REG_ICASE para que las coincidencias no distingan entre mayúsculas y minúsculas, o REG_NOSUB si no necesita las posiciones de las subcoincidencias.

regcomp() devuelve 0 cuando la compilación se realiza correctamente. Un valor distinto de cero es un código de error; no es un valor de errno. Use regerror() con el mismo objeto regex_t para generar un mensaje de diagnóstico. Llame a regfree() únicamente después de una compilación correcta.

Comparar cadenas con regexec() y liberar la expresión regular compilada

Llame a regexec() con el objeto regex_t compilado y una cadena terminada en NUL. El valor de retorno 0 indica que hay una coincidencia, mientras que REG_NOMATCH indica que el patrón no coincidió. Cualquier otro valor señala un error de ejecución y se puede convertir en un mensaje con regerror(). Si necesita las posiciones de las subcoincidencias, proporcione una matriz de elementos regmatch_t y su capacidad; la primera entrada describe la coincidencia completa. Con REG_NOSUB, no solicite posiciones de subcoincidencias.

Este ejemplo completo compila un patrón, prueba dos cadenas y libera el objeto compilado. Informa de los errores de compilación y ejecución mediante regerror(). En la ejecución correcta suministrada, imprimió match y luego no match, y terminó con el código 0. Las etiquetas match y no match que muestra el ejemplo permanecen en inglés.

Ejecute este ejemplo:

#include <regex.h>
#include <stddef.h>
#include <stdio.h>

int main(void) {
    regex_t re;
    const char *pattern = "[[:alpha:]]+";
    int status = regcomp(&re, pattern, REG_EXTENDED);

    if (status != 0) {
        char message[256];
        regerror(status, &re, message, sizeof message);
        printf("compile: %s\n", message);
        return 1;
    }

    const char *samples[] = {"C language", "123"};
    for (size_t i = 0; i < sizeof samples / sizeof samples[0]; ++i) {
        status = regexec(&re, samples[i], 0, NULL, 0);
        if (status == 0) {
            puts("match");
        } else if (status == REG_NOMATCH) {
            puts("no match");
        } else {
            char message[256];
            regerror(status, &re, message, sizeof message);
            printf("execution: %s\n", message);
        }
    }

    regfree(&re);
    return 0;
}
match
no match

El ejemplo comprueba cada valor de retorno antes de usarlo y conserva la expresión compilada hasta haber probado ambas cadenas. La ejecución suministrada terminó con el código 0. El ejemplo requiere una implementación POSIX de <regex.h>.