regcomp(), regexec(), la gestion des ER
Description
Les fonctions regcomp() et regexec() sont des fonctions disponibles dans la bibliothèque de fonctions du compilateur C de GNU. Elles permettent l’utilisation d’expressions régulières basiques ou étendues par un programme, évitant ainsi aux programmeurs d’avoir à développer eux-mêmes des analyseurs syntaxiques compliqués.
L’implémentation libre de ces fonctions a été effectuée par Henry Spencer en 1986.
Les fonctions originelles correspondantes sous Unix s’appellaient regcmp() et regex().
On notera également qu’il a existé une commande regcmp qui permettait la génération d’expressions régulières compilées qu’il était possible d’inclure dans un programme source. Le but était de gagner du temps à l’exécution en évitant d’avoir à compiler les expressions lors de l’exécution du programme faisant appel à regex(). L’intérêt était relativement limité car le principe imposait que les expressions fussent connues à la compilation, ce qui interdisait toute définition dynamique des expression...
Rappel du principe de fonctionnement
1. Généralités
Les fonctions regcomp() et regexec() permettent de savoir si une chaîne de caractères correspond à une expression régulière, qu’elle soit basique ou étendue.
Pour cela, il faut procéder en deux étapes :
1. |
compiler l’expression régulière que l’on souhaite utiliser. |
2. |
comparer la chaîne de caractères à l’expression régulière en utilisant l’expression régulière compilée précédemment. |
La première étape est effectuée par regcomp(). Cette fonction transforme l’expression régulière en un ensemble de données directement utilisables par la fonction regexec(). L’étape de compilation ne nécessite d’être effectuée qu’une seule fois pour chaque expression régulière à traiter.
La deuxième étape est effectuée autant de fois que nécessaire pour tester la correspondance entre différentes chaînes de caractères et l’expression régulière, à l’aide de l’expression compilée précédemment.
Les informations de référence données ci-dessous sont extraites du manuel du programmeur Linux.
2. Utilisation
L’utilisation de ces deux fonctions dans un programme C nécessite l’inclusion de deux fichiers headers grâce aux deux lignes suivantes :
#include <sys/types.h>
#include <regex.h>
Les prototypes des fonctions, données par leur page de manuel, sont les suivants :
int regcomp(regex_t *preg, const char *regex, int cflags);
int regexec(const regex_t *preg, const char *string,
size_t nmatch, regmatch_t pmatch[], int eflags);
Des fonctions associées permettent respectivement de gérer les erreurs et de libérer la mémoire :
size_t regerror(int errcode, const regex_t *preg, char *errbuf,
size_t errbuf_size);
void regfree(regex_t *preg);
3. Utilisation de regcomp()
La fonction regcomp() permet la compilation d’une expression régulière....
Exercices
1. Exercice 1
Créer un programme comparant une chaîne de caractères (passée en argument 2) à une expression régulière basique (passée en argument 1).
Afficher VRAI s’il y a correspondance entre une sous-chaîne (ou la chaîne complète) et l’expression régulière, et FAUX dans le cas contraire.
Afficher les paramètres passés : expression régulière et chaîne de caractères.
On testera les couples suivants :
1 |
a*b et cabd |
2 |
a*b et caabd |
3 |
a*b et cbd |
4 |
aa*b et cbd |
5 |
aa*b et cabd |
Solution
#include <stdio.h>
#include <regex.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *_prgname, *_regexp, *_string;
int _cflags, _eflags;
regex_t _reg;
_prgname = argv[0];
/* Controle des arguments
~~~~~~~~~~~~~~~~~~~~~~ */
if (argc != 3) {
fprintf(stderr, "Usage: %s regexp string\n", _prgname);
exit(1);
}
_regexp = argv[1];
_string = argv[2];
_cflags = 0;
_eflags = 0;
/* Affichage des parametres recus
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
printf("EXPRESSION = [%s]\n", _regexp);
printf("CHAINE = [%s]\n", _string);
/* Compilation de l'expression reguliere
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if (regcomp(&_reg, _regexp, _cflags) != 0) {
fprintf(stderr, "%s: regcomp error for \"%s\" !\n",
_prgname, _regexp);
exit(1);...