Page suivante Page précédente   Table des matières  

4. Expressions régulières en C

Par Ben Tindale Ben.Tindale@aals27.alcatel.com.au

4.1 Introduction

Dans cette série d'articles, j'ai l'intention d'explorer les implantations variées des chaînes de caractères dans les langages communs à la plate-forme Linux. Le premier article explorera la bibliothèques d'expressions régulières fournie avec GNU libc. Dans les articles suivants, j'espère voir les autres bibliothèques usuelles et les langages -- les fonctions de tri par fonction de hashage (hash functions) en Java et les chaînes dans KDE versus les chaînes dans Gnome.

Chaque langage a ses forces et ses faiblesses. J'espère qu'en faisant une partie du travail à votre place, je serai capable de vous donner un bref aperçu des capacités et des lacunes des langages les plus communs et de leurs bibliothèques en regard à la manipulation de chaînes de caractères.

Je ne parlerai ni d'internationalisation ni de localisation dans cette série d'articles, puisque ces sujets méritent des volumes complets d'études et non un bref exposé.

4.2 La Bibliothèque GNU C et les expressions régulières

La bibliothèque GNU C est l'élément de base de toute installation Linux du point de vue du programmeur. La plupart des bibliothèques de niveau plus élevé sont basées sur libc, et la plupart des éléments que l'on considère comme faisant partie du langage C sont en fait des fonctions de libc.

Les chaînes de caractères en C sont juste des tableaux de caractères (caractères simples ou étendus), terminés par un caractère nul. C'est la plus simple et la plus efficace des implantations de chaînes en termes de ressources de calcul, mais c'est aussi probablement la plus compliquée et la moins efficace pour le programmeur. Puisque les chaînes sont soit des constantes (ie. des valeurs littérales) soit des pointeurs, le programmeur à la possibilité de manipuler les chaînes jusqu'au niveau des bits et a toutes sortes d'opportunités pour optimiser son code (par exemple ce bout de code). D'un autre coté, la terminaison nulle des chaînes et l'absence de vérification intégrée de la longueur, annonce que des problèmes tels que des boucles infinies et des débordements de capacité vont apparaître inévitablement dans le code.

La bibliothèque GNU C est riche en fonctions de manipulation de chaînes. Il y a les appels standards pour la copie, le déplacement, la concaténation, la comparaison et pour trouver la longueur d'une chaîne (ou d'une zone mémoire). En plus de tout cela, libc supporte aussi le découpage en sous-chaînes (tokenization) et la recherche d'expressions régulières.

L'utilisation des expressions régulières est une méthode puissante pour rechercher un texte correspondant à un motif particulier. La plupart des utilisateurs ont rencontré le principe d'expression régulière pour la première fois sur la ligne de commande, où des caractères comme l'astérisque ont une signification particulière (dans ce cas, remplacer aucun ou plusieurs caractères). Pour démontrer la puissance des expressions régulières et comment les utiliser, nous écrirons une forme simplifiée de grep.

4.3 Mygrep.c

Mygrep.c utilise la puissante bibliothèque regex.h pour faire sa recherche à travers un fichier texte afin de trouver une ligne qui correspond au motif donné.

bash> ./mygrep -f mygrep.c -p int Line 17: int match_patterns(regex_t *r, FILE *FH) Line 36: printf("Line %d: %s", line_no, line); Line 52: printf("In error\n"); bash>

Libc rend l'utilisation des expressions régulières relativement aisée. Bien sûr, il serait plus facile d'utiliser un langage qui supporterait directement les expressions régulières (comme perl) pour cet exemple, mais la bibliothèque C a l'avantage d'une intégration facile au code existant et probablement d'un gain en vitesse d'exécution (bien que dans les langages comme perl, les expressions régulières sont fortement optimisées).

Si vous examinez le code du programme, vous verrez que mygrep.c est principalement axé autour d'une fonction qui manipule les options de l'utilisateur et de deux fonctions qui font le travail d'appariement de l'expression régulière. La première de ces fonctions est, logiquement, do_regex(). Cette fonction prend comme paramètres un pointeur sur une structure d'expression régulière, une chaîne contenant le motif à rechercher et une chaîne contenant le nom du fichier. La première tâche de do_regex() est de « compiler » l'expression régulière dans un format natif à la bibliothèque GNU en appelant regcomp(). Ce format est une structure de données optimisée pour l'appariement de motif, les détails de ce dernier étant cachés à l'usager. Ensuite, le fichier à balayer est ouvert, puis l'identificateur de fichier et l'expression régulière compilée sont passés à match_patterns() pour l'exécution de la recherche et l'affichage des résultats.

match_patterns() balaie chaque ligne du fichier, recherchant des motifs qui s'apparieraient à l'expression régulière. On commence par balayer les lignes une à une -- remarquez que nous avons fait l'hypothèse que chaque ligne fait moins de 1023 octets (le tableau appelé line fait 1024 octets et nous avons besoin d'un caractère pour la terminaison nulle). Si la ligne fait plus de 1023 octets, elle est alors coupée et le reste interprété comme une nouvelle ligne jusqu'à ce que le caractère \n soit rencontré. La fonction regexec() balaie la ligne à la recherche d'un ensemble de caractères qui correspond au motif spécifié par l'utilisateur. Chaque ensemble de caractères qui correspond à l'expression régulière force regexec() à retourner 0, provoquant l'affichage de la ligne ainsi que de son numéro. Si l'expression régulière s'apparie plus d'une fois sur la même ligne, la ligne est imprimée autant de fois. Le décalage à partir du début de la ligne est mis à jour de sorte que le motif correspondant n'est pas le même à chaque fois.

Cet exemple, bien que très simple, démontre à quel point la bibliothèque GNU C peut être puissante. Quelques unes des capacités les plus remarquables de la bibliothèque que nous avons utilisées sont :

En particulier, nous avons exploré la puissante bibliothèque d'expressions régulières GNU regex.h, qui simplifie l'utilisation de la recherche d'expressions régulières dans vos programmes, et fournit une interface simple et sûre à son utilisation.

Copyright 2000, Ben Tindale. Paru dans le numéro 55 de la Linux Gazette de juillet 2000.

Traduction française de Fabien Niñoles fabien@tzone.org.


Page suivante Page précédente   Table des matières