Solución:
Las expresiones regulares en realidad no son parte de ANSI C. Parece que podría estar hablando de la biblioteca de expresiones regulares POSIX, que viene con la mayoría (¿todos?) * Nixes. Aquí hay un ejemplo del uso de expresiones regulares POSIX en C (basado en esto):
#include <regex.h>
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(®ex, "^a[[:alnum:]]", 0);
if (reti) {
fprintf(stderr, "Could not compile regexn");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, "abc", 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %sn", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
Alternativamente, es posible que desee consultar PCRE, una biblioteca para expresiones regulares compatibles con Perl en C. La sintaxis de Perl es más o menos la misma sintaxis que se usa en Java, Python y varios otros lenguajes. La sintaxis POSIX es la sintaxis utilizada por grep
, sed
, vi
etc.
Probablemente no sea lo que desea, pero una herramienta como re2c puede compilar expresiones regulares POSIX (-ish) en ANSI C.Está escrito como un reemplazo de lex
, pero este enfoque le permite sacrificar la flexibilidad y la legibilidad por el último bit de velocidad, si realmente lo necesita.
man regex.h
informa que no hay una entrada manual para regex.h, pero man 3 regex
le ofrece una página que explica las funciones POSIX para la coincidencia de patrones.
Las mismas funciones se describen en The GNU C Library: Regular Expression Matching, que explica que la GNU C Library admite tanto la interfaz POSIX.2 como la interfaz que la GNU C Library ha tenido durante muchos años.
Por ejemplo, para un programa hipotético que imprime cuál de las cadenas pasadas como argumento coincide con el patrón pasado como primer argumento, podría usar un código similar al siguiente.
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_regerror (int errcode, size_t length, regex_t *compiled);
int
main (int argc, char *argv[])
{
regex_t regex;
int result;
if (argc < 3)
{
// The number of passed arguments is lower than the number of
// expected arguments.
fputs ("Missing command line argumentsn", stderr);
return EXIT_FAILURE;
}
result = regcomp (®ex, argv[1], REG_EXTENDED);
if (result)
{
// Any value different from 0 means it was not possible to
// compile the regular expression, either for memory problems
// or problems with the regular expression syntax.
if (result == REG_ESPACE)
fprintf (stderr, "%sn", strerror(ENOMEM));
else
fputs ("Syntax error in the regular expression passed as first argumentn", stderr);
return EXIT_FAILURE;
}
for (int i = 2; i < argc; i++)
{
result = regexec (®ex, argv[i], 0, NULL, 0);
if (!result)
{
printf ("'%s' matches the regular expressionn", argv[i]);
}
else if (result == REG_NOMATCH)
{
printf ("'%s' doesn't the regular expressionn", argv[i]);
}
else
{
// The function returned an error; print the string
// describing it.
// Get the size of the buffer required for the error message.
size_t length = regerror (result, ®ex, NULL, 0);
print_regerror (result, length, ®ex);
return EXIT_FAILURE;
}
}
/* Free the memory allocated from regcomp(). */
regfree (®ex);
return EXIT_SUCCESS;
}
void
print_regerror (int errcode, size_t length, regex_t *compiled)
{
char buffer[length];
(void) regerror (errcode, compiled, buffer, length);
fprintf(stderr, "Regex match failed: %sn", buffer);
}
El último argumento de regcomp()
necesita ser al menos REG_EXTENDED
, o las funciones usarán expresiones regulares básicas, lo que significa que (por ejemplo) necesitaría usar a{3}
en lugar de a{3}
usado a partir de expresiones regulares extendidas, que es probablemente lo que espera usar.
POSIX.2 también tiene otra función para la coincidencia de comodines: fnmatch()
. No permite compilar la expresión regular u obtener las subcadenas que coinciden con una subexpresión, pero es muy específico para verificar cuándo un nombre de archivo coincide con un comodín (por ejemplo, usa el FNM_PATHNAME
bandera).