Bonjour !
Je vous propose un exemple d'utilisation basique de l'API de la bibliothèque PCRE (Perl Compatible Regular Expressions). L'exemple utilise l'unité pcre_dll de Renato Mancuso.
On utilise assez rarement l'API de la bibliothèque PCRE, à cause de son caractère disons ésotérique. Voici un exemple en Pascal.
Quelques commentaires. Les résultats de la recherche sont conservés dans un tableau de nombres entiers. Il y a deux nombres par sous-chaîne : respectivement la position (dans le sujet) du premier et du dernier caractère de la sous-chaîne. La taille du tableau est égale à trois fois fois le nombre de sous-chaînes (sous-chaîne principale et captures).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 {$codepage utf8} {$mode delphi} uses sysutils, pcre_dll; { http://renatomancuso.com/software/dpcre/dpcre.htm } type pcre = TPcreH; const SUJET1 = '_27/09/2016_'; MOTIF1 = '(\d{2})/(\d{2})/(\d{4})'; CAPTURES = 3; TAILLE_TABLEAU = 3 * (CAPTURES + 1); var regex: pcre; motif: pchar; message_erreur: pchar; position_erreur: integer; resultat: integer; sujet: pchar; tableau: array[0..TAILLE_TABLEAU - 1] of integer; index: integer; souschaine: ansistring; begin WriteLn(Format('PCRE version %s', [pcre_version()])); motif := MOTIF1; regex := pcre_compile( motif, 0, message_erreur, position_erreur, nil ); if regex = nil then begin WriteLn(Format('La compilation de l''expression régulière a échoué. Erreur à la position %d : "%s"', [position_erreur, message_erreur])); WriteLn(Format(' %s', [motif])); WriteLn(Format(' %s^', [StringOfChar(' ', position_erreur)])); end else begin sujet := SUJET1; resultat := pcre_exec( regex, nil, sujet, StrLen(sujet), 0, 0, @tableau[0], TAILLE_TABLEAU ); if resultat < 0 then begin case resultat of PCRE_ERROR_NOMATCH: WriteLn('Pas de correspondance trouvée.'); else WriteLn(Format('Erreur %d.', [resultat])); end; end else begin if resultat = 0 then begin resultat := TAILLE_TABLEAU div 3; WriteLn(Format('Le tableau ne peut contenir que %d sous-chaîne(s).', [resultat])); end; WriteLn('| index | sous-chaîne'); WriteLn('+-------+------------'); for index := 0 to resultat - 1 do begin souschaine := Copy( StrPas(sujet), tableau[2 * index] + 1, tableau[2 * index + 1] - tableau[2 * index] ); WriteLn(Format('| %d | "%s"', [index, souschaine])); end; end; pcre_free(regex); end; end.
Pourquoi trois fois et pas deux fois ? Parce que le dernier tiers du tableau est utilisé de façon privée par la bibliothèque, comme cela est expliqué dans la documentation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 const SUJET1 = '_27/09/2016_'; MOTIF1 = '(\d{2})/(\d{2})/(\d{4})'; CAPTURES = 3; TAILLE_TABLEAU = 3 * (CAPTURES + 1);
Autre chose à remarquer, c'est qu'il y a deux étapes dans le programme : la compilation de l'expression régulière et l'exécution de la recherche. Il y a des erreurs à la compilation et des erreurs à l'exécution.
Pour provoquer une erreur de compilation dans le programme ci-dessus, remplacez le motif par un autre qui ne soit pas correct, par exemple :
Vous obtiendrez le résultat suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 const ... MOTIF1 = '[3-1]';
Code X : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 PCRE version 6.7 04-Jul-2006 La compilation de l'expression régulière a échoué. Erreur à la position 3 : "range out of order in character class" [3-1] ^
Concernant les erreurs d'exécution, la première chose à savoir est que l'absence de correspondance trouvée est considérée comme une erreur. Il faut donc la traiter à part.
Autre cas à traiter en particulier : si le tableau déclaré pour contenir les résultats est trop petit, la fonction pcre_exec() renvoie la valeur 0. On peut quand même consulter les résultats mais en tenant compte du nombre de sous-chaînes disponibles.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 if resultat < 0 then begin case resultat of PCRE_ERROR_NOMATCH: WriteLn('Pas de correspondance trouvée.'); else WriteLn(Format('Erreur %d.', [resultat])); end;
Ainsi, si vous donnez à la constante CAPTURES la valeur 2, vous obtiendrez le résultat suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if resultat = 0 then begin resultat := TAILLE_TABLEAU div 3; WriteLn(Format('Le tableau ne peut contenir que %d sous-chaîne(s).', [resultat])); end;
Code X : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 PCRE version 6.7 04-Jul-2006 Le tableau ne peut contenir que 3 sous-chaîne(s). | index | sous-chaîne +-------+------------ | 0 | "27/09/2016" | 1 | "27" | 2 | "09"
Quand tout se passe bien, la fonction pcre_exec() renvoie le nombre de sous-chaînes trouvées (sous-chaîne principale et captures). Il n'y a plus qu'à aller chercher la sous-chaîne dans le sujet, par exemple au moyen de la fonction Copy() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 for index := 0 to resultat - 1 do begin souschaine := Copy( StrPas(sujet), tableau[2 * index] + 1, tableau[2 * index + 1] - tableau[2 * index] );
Code X : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 PCRE version 6.7 04-Jul-2006 | index | sous-chaîne +-------+------------ | 0 | "27/09/2016" | 1 | "27" | 2 | "09" | 3 | "2016"
Ci-joint un deuxième exemple, qui montre comment rechercher les occurrences multiples d'un motif.
Partager