IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Pascal Discussion :

Utiliser l'API de la bibliothèque PCRE


Sujet :

Contribuez Pascal

  1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut Utiliser l'API de la bibliothèque PCRE
    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.

    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.
    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
    const
      SUJET1 = '_27/09/2016_';
      MOTIF1 = '(\d{2})/(\d{2})/(\d{4})';
      CAPTURES = 3;
      TAILLE_TABLEAU = 3 * (CAPTURES + 1);
    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.

    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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const
      ...
      MOTIF1 = '[3-1]';
    Vous obtiendrez le résultat suivant :

    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.

    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;
    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
          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;
    Ainsi, si vous donnez à la constante CAPTURES la valeur 2, vous obtiendrez le résultat suivant :

    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.
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

Discussions similaires

  1. Réponses: 0
    Dernier message: 03/04/2013, 10h28
  2. Holla : une bibliothèque JavaScript facilitant l'utilisation des API WebRTC
    Par FirePrawn dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 21/02/2013, 10h03
  3. []Recuperer le nom d'un contact en utilisant les API msn ?
    Par trotter dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 09/10/2005, 22h07
  4. Réponses: 36
    Dernier message: 13/05/2004, 18h22
  5. Utilisation des API MySQL // ADO ou BDE ? (sujet 2)
    Par rohstev dans le forum C++Builder
    Réponses: 8
    Dernier message: 07/11/2003, 10h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo