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

Langage PHP Discussion :

Gérer les balises complexes en pseudo phpbb [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre expérimenté
    Avatar de Rakken
    Homme Profil pro
    Inscrit en
    Août 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 257
    Points : 1 341
    Points
    1 341
    Par défaut Gérer les balises complexes en pseudo phpbb
    Bonjour,

    Je me suis fait il y a quelques temps un parseur de pseudo-bbcode. Il marche bien mis à part un point bien précis que je n'arrive pas à résoudre malgré pas mal d'arrachage de cheveux.

    Voici le cas qui foire :
    Avec [livre] qui n'est pas une balise (donc que je veux laisser tel quel).

    Et l'expression la plus fiable que j'ai pu trouver :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $textarea = preg_replace_callback("/(\[([\w]+)[^\]]*\])(.*)(\[\/\\2(.*)\])/U", array($this, "_baliseComplexeVersHtml"), $textarea);
    La fonction _baliseComplexeVersHtml ira me chercher en base la définition n°1 de "coucou", pour faire le remplacement.

    Le problème vient du fait que \\2 ne récupère visiblement qu'une seule lettre au lieu de toute la chaine, du coup, j'ai rajouté le (.*), pour avoir la fin, mais ce n'est plus discriminant.
    Donc sur un cas comme "[l88]test[/l88], ca marche, mais si une autre balise qui commence par l est juste devant, comme dans l'exemple, ce qui est pris en compte, va de la première balise a la balise fermante.

    Ce que _baliseComplexeVersHtml reçois est par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Array
    (
        [0] => [l1]coucou[/l1]
        [1] => [l1]
        [2] => l
        [3] => coucou
        [4] => [/l1]
        [5] => 1
    )
    Et parce que sinon c'est trop simple, les cas que je veux pouvoir gérer sont par exemple :
    [m|12]test[/m] ==> envoyé en traitement
    [m5|12]test[/m5]
    [livre][l88][lune][/l88]

    Bref, si un dieu des regexp passe dans le coin, je l'en remercie d'avance ;-)

  2. #2
    Membre averti Avatar de BornBanane
    Homme Profil pro
    dev
    Inscrit en
    Mars 2007
    Messages
    284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : dev

    Informations forums :
    Inscription : Mars 2007
    Messages : 284
    Points : 416
    Points
    416
    Par défaut
    Salut,

    J'ai testé ta regexp sans mettre le (.*) après le \2 et pour moi cela fonctionne, enfin à ce que j'ai compris de ton soucis.

    Voilà ce que j'ai fait comme test (PHP 5.3)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <?php
     
    $s = "[erfrefref][l88|lrfrerferferferf][lune][/l88]";
     
    $t = preg_match('`(\[([\w]+)[^\]]*\])(.*)(\[\/\2\])`' , $s , $res );
     
     
    var_dump($res);
    Et voila mon résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    array
      0 => string '[l88|lrfrerferferferf][lune][/l88]' (length=34)
      1 => string '[l88|lrfrerferferferf]' (length=22)
      2 => string 'l88' (length=3)
      3 => string '[lune]' (length=6)
      4 => string '[/l88]' (length=6)
    Je pense que ça donne ce que tu voulais : ça match bien que le tag qui est fermé et ça n'empêche pas d'avoir un paramètre dans le tag ouvrant.

  3. #3
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Hélas BornBanane, ta RE ne marche que pour les chaïnes similaires à la tienne
    "[erfrefref][l88|lrfrerferferferf][lune][/l88]"
    c’est à dire justement les cas pour lequels il n’y a pas de problème.

    Les problèmes n’apparaissent que quand une balise commençant par au moins une même lettre que la balise ouvrante précède celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [livre][li|678]marron/li]
    pose un problème mais pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [vivre][li|678]marron/li]

  4. #4
    Membre expérimenté
    Avatar de Rakken
    Homme Profil pro
    Inscrit en
    Août 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 257
    Points : 1 341
    Points
    1 341
    Par défaut
    Tout à fait eyquem.
    C'est un cas finalement très spécifique. Hélas il est arrivé pour certains articles.
    Normalement, les balises simples sont éliminées dans une première passe, mais là, la personne a voulu écrire un truc du genre
    citation : "[les habitants] aiment les [l1]pommes[/l1]"
    Avec "[les habitants]" qui n'est pas une balise, mais bien un texte qu'il faut laisser entre crochet après interprétation, d'où la détection de mon problème.

  5. #5
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Bonjour,



    J’ai eu du mal à saisir le problème parce qu’il est mal expliqué.

    Heureusement que tu as mis les 3 derniers exemples.
    '[m|12]test[/m]' et '[m5|12]test[/m5]' à matcher
    montrent que tu es obligé de mettre une partie [^\]]* dans la RE pour attraper '|12' ,
    mais ce faisant la RE foire alors sur les chaines du genre '[livre][li]coucou[/li]' car ce qui doit matcher avec 'li' dans '[/li]' et qui est censé matcher avec ’li’ dans ’[li]’ matche en fait de façon anticipée dans ’[livre]’.




    Je ne sais pas comment tu t’es mis dans la mélasse suivante:

    1) avec ou sans (.*) après \\2 , ta RE sur '[livre][li]coucou[/li]' produit '[li]coucou'
    Donc mettre (.*) après \\2 n'arrange rien.

    2) Par contre tu as dû te tromper en mettant '[livre][l1]coucou[/l1]' dans ton message, c'est à dire avec '1' dans ’l1’ au lieu de 'i' .
    Sans doute as tu fais des essais avec cette coquille sans t'en apercevoir. De ce fait, c'est avec ta RE comportant \\2(.+) que [^\]]* matche effectivement avec ’ivre’ et que \\2 ne matche qu'avec une seule lettre, parce qu’il n’y a que le ’l’ qui se trouve à la fois dans ’livre’ et dans ’l1’. Une seule lettre ainsi concernée, c’est un cas limite, mais il y a encore un matching qui peut se faire, qui donne '[l1]coucou'
    Cependant ce match est la conséquence de la présence de (.+) dans la RE. Ça ne peut donc pas être sa motivation.


    En résumé, sur
    '[livre][l1]coucou[/l1]' , la RE sans (.+) donne le résultat attendu ’coucou’, et la RE avec \\2(.+) donne '[l1]coucou'
    tandis que sur
    '[livre][li]coucou[/li]' le résultat est faux dans les deux cas.


    Je me suis aussi fait piéger un bon moment par le '1' dans ’l1’ que j’ai pris pour un ’i’ et par tes propos que je ne comprenais pas.
    J’ai eu un peu de mal à me dépétrer de ces confusions.




    ----------------------------------------------------



    Une fois qu’il m’a semblé avoir compris le problème, je l’ai pris à l’envers, c’est à dire en commençant par la balise fermante, puisque c’est elle qui commande le matching finalement.

    Si j’ai bien compris ce qu’est un système de balises, il n’y a qu’un nombre limité de mots qui sont identifiables par le système comme pouvant participer à des balises. Il y a donc une liste finie de mots de balises et ces mots sont les seuls qui puissent se trouver dans une balise de fermeture.

    Je pars donc de l’idée que dans une balise de fermeture '[/A]' , la partie A se trouve entièrement en amont dans la balise d’ouverture, seule cette dernière pouvant présenter la forme [Ax] avec une partie x supplémentaire.





    L’écriture de [^\[]* ou [^\[\]]* pour capter ce qui est au centre
    ~(\[([\w]+)[^\]]*\])([^[]*)(\[\/\\2(.*)\])~U
    conviendrait s’il n’y avait pas le 3 ième exemple qui montre que tu dois pouvoir appliquer la regex à des chaînes dont l’entre-balises contient des ’[’ et ’]’







    Si la balise fermante ne peut être que du type '[/A]' , alors ce n’est vraiment pas une bonne idée de vouloir matcher 'A' avec quelque chose du style \\2(.+)
    Il faut partir de \[/\\2\] comme base, pour matcher '[/A]' ( nota: à quoi sert \ devant / ? )


    Le problème avec des motifs tels que '[buvard][bu]coucou[/bu]' et '[buvard][bu|66]coucou[/bu]', c’est que 'A' est 'bu' et se trouve en amont dans 'buvard'. Il ne me semble pas possible de trouver une partie de RE qui détecte 'bu|66' mais pas 'buvard', à moins de savoir que 'bu|66' fait partie de noms de balise autorisés et que 'buvard' n’en fait pas partie.

    Nota:
    '[livre][l1]coucou[/l1]' est en réalité un cas précisément identique à '[buvard][bu|66]coucou[/bu]' et non pas à '[buvard][bu]coucou[/bu]' , à cause du fait que dans '[l1]' c’est '1' et non pas 'i'.
    - Comme '[livre][l1]coucou[/l1]' est confusionnant, je préfère raisonner sur de chaines comme '[buvard][bu|66]coucou[/bu]'




    ----------------------------------------------------------



    La regex construite dans ton message, Rakken, n’attrape pas les motifs correctement parce que l’absence de condition dans (.*) fait que \[([\w]+) matche avec le début de n’importe quelle première balise qui se présente.
    M’excuserez, mais j’ai fait les tests en Python, c’est plus simple.
    Les résultats sont identiques en terminant ta RE par \[/\\2\] ou par \[/\\2(.+)\] :



    Code python : 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
    import re
    lesch = ('[buffet][bu]chene[/bu]',
             '[buvard][bu|342]coucou[/bu]',
             '[buffet][bu][BOIS][/bu]',
             '[buvard][bu|676][GEAI][/bu]',
             '[bunker][buffet][bu]chene[/bu]',
             '[bunker][buvard][bu|342]coucou[/bu]',
             '[bunker][buffet][bu][BOIS][/bu]',
             '[bunker][buvard][bu|676][GEAI][/bu]',
     
             '[buffet]le[bu]chene[/bu]',
             '[buvard]le[bu|444]coucou[/bu]',
             '[buffet]le[bu][BOIS][/bu]',
             '[buvard]le[bu|444][GEAI][/bu]',
             '[bunker][buffet]le[bu]chene[/bu]',
             '[bunker][buvard]le[bu|444]coucou[/bu]',
             '[bunker][buffet]le[bu][BOIS][/bu]',
             '[bunker][buvard]le[bu|444][GEAI][/bu]',
     
             '[buffet][bu]bureau[/bu]',
             '[buvard][bu|999]butiner[/bu]',
             '[buffet][bu][buREAU][/bu]',
             '[buvard][bu|999][buTINER][/bu]',
             '[bunker][buffet][bu]bureau[/bu]',
             '[bunker][buvard][bu|999]butiner[/bu]',
             '[bunker][buffet][bu][buREAU][/bu]',
             '[bunker][buvard][bu|999][buTINER][/bu]',
     
             '[buffet]le[bueno]bureau[/bu]',
             '[buvard]pour[bumi|999]butiner[/bu]',
             '[buffet]le[bueno][buREAU][/bu]',
             '[buvard]pour[bumi|999][buTINER][/bu]',
             '[bunker][buffet][bueno]bureau[/bu]',
             '[bunker][buvard][bumi|999]butiner[/bu]',
             '[bunker][buffet][bueno][buREAU][/bu]',
             '[bunker][buvard][bumi|999][buTINER][/bu]',
     
             '[mistral][mi]vent[/mi][/mistral]',
             '[buche][bu][NOEL][/bu][/buche]',
             '[zebulon][ze|67][ze][/ze]',
             '[poreux][po]le[po]poreux[/po]',
             '[poreux][po]le[po][poROSITE][/po]')
     
     
    for i,RE in enumerate((
        '(\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])',
        #        RE0 de Rakken sans (.*)
        '\[(\w+)([^\]]*)\]'+'(?!\[\\1)'+'(.+)'+'(\[/\\1\])',
        #                    (?!\[\\1)                     RE 1
        '\[(\w+)([^\]]*)\]' + '(?![^\[]*\[\\1)' + '(.+)' + '(\[/\\1\])',
        #                     '(?![^\[]*\[\\1)'            RE 2
        '\[(\w+)([^\]]*)\]' + '(?![^\[]*\[\\1(?(2).))' + '(.+)' + '(\[/\\1\])',
        #                     '(?![^\[]*\[\\1(?(2).))'     RE 3  (?(2).) en plus
        '\[(\w+)([^\]]*)\]' + '(?!.*\[\\1)' + '(.+)' + '(\[/\\1\])',
        #                     '(?!.*?\[\\1)'                RE4  .* au lieu de [^\[]*, change rien
        '\[(\w+)([^\]]*)\]' + '(((?!\[\\1.).)+)' + '(\[/\\1\])',
        #                     '(((?!\[\\1.).)+)'           RE5  point verificateur
        )):
        print repr(RE)+'\t\t'+str(i)
        pat = re.compile(RE)
        ecr = ''
        for ch in lesch:
            if pat.search(ch):
                if ch==in('[buffet]le[bu]chene[/bu]',
                          '[buffet][bu]bureau[/bu]',
                          '[buffet]le[bueno]bureau[/bu]',
                          '[mistral][mi]vent[/mi][/mistral]'):
                    ecr += '\n'
                li = [repr(u) for u in pat.search(ch).groups()]
                ecr += ch.rjust(39)+'   '+li[0].ljust(9)+' , '+li[1].ljust(10)+' , '+li[2].ljust(18)+' , '+li[3].ljust(9)+'\n'
            else:
                ecr += ch.rjust(39)+'  '+'~~~~~~~~~\n'
        ecr += '\n'
        print ecr



    RE Rakken
    (\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])


    Code python : 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
                     [buffet][bu]chene[/bu]   '[buffet]' , 'bu'       , '[bu]chene'        , '[/bu]'  
                [buvard][bu|342]coucou[/bu]   '[buvard]' , 'bu'       , '[bu|342]coucou'   , '[/bu]'  
                    [buffet][bu][BOIS][/bu]   '[buffet]' , 'bu'       , '[bu][BOIS]'       , '[/bu]'  
                [buvard][bu|676][GEAI][/bu]   '[buvard]' , 'bu'       , '[bu|676][GEAI]'   , '[/bu]'  
             [bunker][buffet][bu]chene[/bu]   '[bunker]' , 'bu'       , '[buffet][bu]chene' , '[/bu]'  
        [bunker][buvard][bu|342]coucou[/bu]   '[bunker]' , 'bu'       , '[buvard][bu|342]coucou' , '[/bu]'  
            [bunker][buffet][bu][BOIS][/bu]   '[bunker]' , 'bu'       , '[buffet][bu][BOIS]' , '[/bu]'  
        [bunker][buvard][bu|676][GEAI][/bu]   '[bunker]' , 'bu'       , '[buvard][bu|676][GEAI]' , '[/bu]'  
     
                   [buffet]le[bu]chene[/bu]   '[buffet]' , 'bu'       , 'le[bu]chene'      , '[/bu]'  
              [buvard]le[bu|444]coucou[/bu]   '[buvard]' , 'bu'       , 'le[bu|444]coucou' , '[/bu]'  
                  [buffet]le[bu][BOIS][/bu]   '[buffet]' , 'bu'       , 'le[bu][BOIS]'     , '[/bu]'  
              [buvard]le[bu|444][GEAI][/bu]   '[buvard]' , 'bu'       , 'le[bu|444][GEAI]' , '[/bu]'  
           [bunker][buffet]le[bu]chene[/bu]   '[bunker]' , 'bu'       , '[buffet]le[bu]chene' , '[/bu]'  
      [bunker][buvard]le[bu|444]coucou[/bu]   '[bunker]' , 'bu'       , '[buvard]le[bu|444]coucou' , '[/bu]'  
          [bunker][buffet]le[bu][BOIS][/bu]   '[bunker]' , 'bu'       , '[buffet]le[bu][BOIS]' , '[/bu]'  
      [bunker][buvard]le[bu|444][GEAI][/bu]   '[bunker]' , 'bu'       , '[buvard]le[bu|444][GEAI]' , '[/bu]'  
     
                    [buffet][bu]bureau[/bu]   '[buffet]' , 'bu'       , '[bu]bureau'       , '[/bu]'  
               [buvard][bu|999]butiner[/bu]   '[buvard]' , 'bu'       , '[bu|999]butiner'  , '[/bu]'  
                  [buffet][bu][buREAU][/bu]   '[buffet]' , 'bu'       , '[bu][buREAU]'     , '[/bu]'  
             [buvard][bu|999][buTINER][/bu]   '[buvard]' , 'bu'       , '[bu|999][buTINER]' , '[/bu]'  
            [bunker][buffet][bu]bureau[/bu]   '[bunker]' , 'bu'       , '[buffet][bu]bureau' , '[/bu]'  
       [bunker][buvard][bu|999]butiner[/bu]   '[bunker]' , 'bu'       , '[buvard][bu|999]butiner' , '[/bu]'  
          [bunker][buffet][bu][buREAU][/bu]   '[bunker]' , 'bu'       , '[buffet][bu][buREAU]' , '[/bu]'  
     [bunker][buvard][bu|999][buTINER][/bu]   '[bunker]' , 'bu'       , '[buvard][bu|999][buTINER]' , '[/bu]'  
     
               [buffet]le[bueno]bureau[/bu]   '[buffet]' , 'bu'       , 'le[bueno]bureau'  , '[/bu]'  
         [buvard]pour[bumi|999]butiner[/bu]   '[buvard]' , 'bu'       , 'pour[bumi|999]butiner' , '[/bu]'  
             [buffet]le[bueno][buREAU][/bu]   '[buffet]' , 'bu'       , 'le[bueno][buREAU]' , '[/bu]'  
       [buvard]pour[bumi|999][buTINER][/bu]   '[buvard]' , 'bu'       , 'pour[bumi|999][buTINER]' , '[/bu]'  
         [bunker][buffet][bueno]bureau[/bu]   '[bunker]' , 'bu'       , '[buffet][bueno]bureau' , '[/bu]'  
     [bunker][buvard][bumi|999]butiner[/bu]   '[bunker]' , 'bu'       , '[buvard][bumi|999]butiner' , '[/bu]'  
       [bunker][buffet][bueno][buREAU][/bu]   '[bunker]' , 'bu'       , '[buffet][bueno][buREAU]' , '[/bu]'  
    [bunker][buvard][bumi|999][buTINER][/bu]   '[bunker]' , 'bu'       , '[buvard][bumi|999][buTINER]' , '[/bu]'  
     
           [mistral][mi]vent[/mi][/mistral]   '[mistral]' , 'mistral'  , '[mi]vent[/mi]'    , '[/mistral]'
             [buche][bu][NOEL][/bu][/buche]   '[buche]' , 'buche'    , '[bu][NOEL][/bu]'  , '[/buche]'
                  [zebulon][ze|67][ze][/ze]   '[zebulon]' , 'ze'       , '[ze|67][ze]'      , '[/ze]'  
              [poreux][po]le[po]poreux[/po]   '[poreux]' , 'po'       , '[po]le[po]poreux' , '[/po]'  
          [poreux][po]le[po][poROSITE][/po]   '[poreux]' , 'po'       , '[po]le[po][poROSITE]' , '[/po]'







    À partir de là, sans recourir à une liste des noms de balise autorisés, on peut améliorer la RE en introduisant une assertion pour empêcher la RE globale de passer sans s’offusquer sur 'bu|66' après avoir matché avec 'buvard' .

    Cette assertion est du type (?!....) pour vérifier qu’il n’y a pas présence d’un '[busuite2]' après un '[busuite1]':

    RE1
    \[(\w+)([^\]]*)\]'.'(?!\[\\1)'.'(.+)'.
    '(\[/\\1\])


    J’écris \w+ à la place de [\w]+ dans laquelle les crochets sont tout à fait inutiles.
    Il ne me paraît pas utile de capter \[([\w]+)[^\]]*\] entre parenthèses, donc \\2 devient \\1



    Code python : 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
                     [buffet][bu]chene[/bu]   'bu'      , ''         , 'chene'            , '[/bu]'  
                [buvard][bu|342]coucou[/bu]   'bu'      , '|342'     , 'coucou'           , '[/bu]'  
                    [buffet][bu][BOIS][/bu]   'bu'      , ''         , '[BOIS]'           , '[/bu]'  
                [buvard][bu|676][GEAI][/bu]   'bu'      , '|676'     , '[GEAI]'           , '[/bu]'  
             [bunker][buffet][bu]chene[/bu]   'bu'      , ''         , 'chene'            , '[/bu]'  
        [bunker][buvard][bu|342]coucou[/bu]   'bu'      , '|342'     , 'coucou'           , '[/bu]'  
            [bunker][buffet][bu][BOIS][/bu]   'bu'      , ''         , '[BOIS]'           , '[/bu]'  
        [bunker][buvard][bu|676][GEAI][/bu]   'bu'      , '|676'     , '[GEAI]'           , '[/bu]'  
     
                   [buffet]le[bu]chene[/bu]   'bu'      , 'ffet'     , 'le[bu]chene'      , '[/bu]'  
              [buvard]le[bu|444]coucou[/bu]   'bu'      , 'vard'     , 'le[bu|444]coucou' , '[/bu]'  
                  [buffet]le[bu][BOIS][/bu]   'bu'      , 'ffet'     , 'le[bu][BOIS]'     , '[/bu]'  
              [buvard]le[bu|444][GEAI][/bu]   'bu'      , 'vard'     , 'le[bu|444][GEAI]' , '[/bu]'  
           [bunker][buffet]le[bu]chene[/bu]   'bu'      , 'ffet'     , 'le[bu]chene'      , '[/bu]'  
      [bunker][buvard]le[bu|444]coucou[/bu]   'bu'      , 'vard'     , 'le[bu|444]coucou' , '[/bu]'  
          [bunker][buffet]le[bu][BOIS][/bu]   'bu'      , 'ffet'     , 'le[bu][BOIS]'     , '[/bu]'  
      [bunker][buvard]le[bu|444][GEAI][/bu]   'bu'      , 'vard'     , 'le[bu|444][GEAI]' , '[/bu]'  
     
                    [buffet][bu]bureau[/bu]   'bu'      , ''         , 'bureau'           , '[/bu]'  
               [buvard][bu|999]butiner[/bu]   'bu'      , '|999'     , 'butiner'          , '[/bu]'  
                  [buffet][bu][buREAU][/bu]  ~~~~~~~~~
             [buvard][bu|999][buTINER][/bu]  ~~~~~~~~~
            [bunker][buffet][bu]bureau[/bu]   'bu'      , ''         , 'bureau'           , '[/bu]'  
       [bunker][buvard][bu|999]butiner[/bu]   'bu'      , '|999'     , 'butiner'          , '[/bu]'  
          [bunker][buffet][bu][buREAU][/bu]  ~~~~~~~~~
     [bunker][buvard][bu|999][buTINER][/bu]  ~~~~~~~~~
     
               [buffet]le[bueno]bureau[/bu]   'bu'      , 'ffet'     , 'le[bueno]bureau'  , '[/bu]'  
         [buvard]pour[bumi|999]butiner[/bu]   'bu'      , 'vard'     , 'pour[bumi|999]butiner' , '[/bu]'  
             [buffet]le[bueno][buREAU][/bu]   'bu'      , 'ffet'     , 'le[bueno][buREAU]' , '[/bu]'  
       [buvard]pour[bumi|999][buTINER][/bu]   'bu'      , 'vard'     , 'pour[bumi|999][buTINER]' , '[/bu]'  
         [bunker][buffet][bueno]bureau[/bu]   'bu'      , 'eno'      , 'bureau'           , '[/bu]'  
     [bunker][buvard][bumi|999]butiner[/bu]   'bu'      , 'mi|999'   , 'butiner'          , '[/bu]'  
       [bunker][buffet][bueno][buREAU][/bu]  ~~~~~~~~~
    [bunker][buvard][bumi|999][buTINER][/bu]  ~~~~~~~~~
     
           [mistral][mi]vent[/mi][/mistral]   'mistral' , ''         , '[mi]vent[/mi]'    , '[/mistral]'
             [buche][bu][NOEL][/bu][/buche]   'buche'   , ''         , '[bu][NOEL][/bu]'  , '[/buche]'
                  [zebulon][ze|67][ze][/ze]  ~~~~~~~~~
              [poreux][po]le[po]poreux[/po]   'po'      , ''         , 'le[po]poreux'     , '[/po]'  
          [poreux][po]le[po][poROSITE][/po]   'po'      , ''         , 'le[po][poROSITE]' , '[/po]'

    Cette RE améliore les choses, '[bu]' ou '[bu|xxx]' ne sont plus captés au sein de (.*) mais l'amélioration est limitée au cas où ’[bu’ suit immédiatement ’[busuite1]’.








    Pour corriger, il suffit d’ajouter [^\[]* dans l’assertion pour la faire avancer jusqu’au premier ’[’ rencontré (s'il y en a un) après un ’[bu]’ ou un ’[busuite1]’ pour faire la vérification de l’absence d'un '[busuite2]'
    La vérification est ainsi faite sur toute la longueur qui s’étend de ’[bu]’ ou ’[busuite1]’ jusqu’à la balise fermante '[/bu]'.

    RE2
    \[(\w+)([^\]]*)\]'.'(?![^\[]*\[\\1)'.'(.+)'.'(\[/\\1\])


    Code python : 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
                     [buffet][bu]chene[/bu]   'bu'      , ''         , 'chene'            , '[/bu]'  
                [buvard][bu|342]coucou[/bu]   'bu'      , '|342'     , 'coucou'           , '[/bu]'  
                    [buffet][bu][BOIS][/bu]   'bu'      , ''         , '[BOIS]'           , '[/bu]'  
                [buvard][bu|676][GEAI][/bu]   'bu'      , '|676'     , '[GEAI]'           , '[/bu]'  
             [bunker][buffet][bu]chene[/bu]   'bu'      , ''         , 'chene'            , '[/bu]'  
        [bunker][buvard][bu|342]coucou[/bu]   'bu'      , '|342'     , 'coucou'           , '[/bu]'  
            [bunker][buffet][bu][BOIS][/bu]   'bu'      , ''         , '[BOIS]'           , '[/bu]'  
        [bunker][buvard][bu|676][GEAI][/bu]   'bu'      , '|676'     , '[GEAI]'           , '[/bu]'  
     
                   [buffet]le[bu]chene[/bu]   'bu'      , ''         , 'chene'            , '[/bu]'  
              [buvard]le[bu|444]coucou[/bu]   'bu'      , '|444'     , 'coucou'           , '[/bu]'  
                  [buffet]le[bu][BOIS][/bu]   'bu'      , ''         , '[BOIS]'           , '[/bu]'  
              [buvard]le[bu|444][GEAI][/bu]   'bu'      , '|444'     , '[GEAI]'           , '[/bu]'  
           [bunker][buffet]le[bu]chene[/bu]   'bu'      , ''         , 'chene'            , '[/bu]'  
      [bunker][buvard]le[bu|444]coucou[/bu]   'bu'      , '|444'     , 'coucou'           , '[/bu]'  
          [bunker][buffet]le[bu][BOIS][/bu]   'bu'      , ''         , '[BOIS]'           , '[/bu]'  
      [bunker][buvard]le[bu|444][GEAI][/bu]   'bu'      , '|444'     , '[GEAI]'           , '[/bu]'  
     
                    [buffet][bu]bureau[/bu]   'bu'      , ''         , 'bureau'           , '[/bu]'  
               [buvard][bu|999]butiner[/bu]   'bu'      , '|999'     , 'butiner'          , '[/bu]'  
                  [buffet][bu][buREAU][/bu]  ~~~~~~~~~
             [buvard][bu|999][buTINER][/bu]  ~~~~~~~~~
            [bunker][buffet][bu]bureau[/bu]   'bu'      , ''         , 'bureau'           , '[/bu]'  
       [bunker][buvard][bu|999]butiner[/bu]   'bu'      , '|999'     , 'butiner'          , '[/bu]'  
          [bunker][buffet][bu][buREAU][/bu]  ~~~~~~~~~
     [bunker][buvard][bu|999][buTINER][/bu]  ~~~~~~~~~
     
               [buffet]le[bueno]bureau[/bu]   'bu'      , 'eno'      , 'bureau'           , '[/bu]'  
         [buvard]pour[bumi|999]butiner[/bu]   'bu'      , 'mi|999'   , 'butiner'          , '[/bu]'  
             [buffet]le[bueno][buREAU][/bu]  ~~~~~~~~~
       [buvard]pour[bumi|999][buTINER][/bu]  ~~~~~~~~~
         [bunker][buffet][bueno]bureau[/bu]   'bu'      , 'eno'      , 'bureau'           , '[/bu]'  
     [bunker][buvard][bumi|999]butiner[/bu]   'bu'      , 'mi|999'   , 'butiner'          , '[/bu]'  
       [bunker][buffet][bueno][buREAU][/bu]  ~~~~~~~~~
    [bunker][buvard][bumi|999][buTINER][/bu]  ~~~~~~~~~
     
           [mistral][mi]vent[/mi][/mistral]   'mistral' , ''         , '[mi]vent[/mi]'    , '[/mistral]'
             [buche][bu][NOEL][/bu][/buche]   'buche'   , ''         , '[bu][NOEL][/bu]'  , '[/buche]'
                  [zebulon][ze|67][ze][/ze]  ~~~~~~~~~
              [poreux][po]le[po]poreux[/po]   'po'      , ''         , 'poreux'           , '[/po]'  
          [poreux][po]le[po][poROSITE][/po]  ~~~~~~~~~


    On attrape cette fois tout correctement.




    Je ne comprends pas ce que j’ai fichu hier. Je n’arrivais pas à obtenir les mêmes résultats, c’était la capture des chaînes commençant par le même mot que la balise de fin qui posait problème, c’est à dire les cas comme ’butyrique’ avec une balise de fin '[/bu]' .
    J’ai cherché un grand moment et j’ai trouvé cette troisième RE en plus, qui donnait de meilleurs résultats :

    RE3
    \[(\w+)([^\]]*)\]'.'(?![^\[]*\[\\1(?(2).))'.'(.+)'.'(\[/\\1\])

    Mais aujourd’hui, la même RE sans la partie (?(2).) , c'est a dire RE2, donne les mêmes résultats.
    Je me suis moi aussi embrouillé.
    Je n’y comprends plus rien, mais l'essentiel est que la précédente RE2 fera l’affaire, je pense.







    Il y a une variante à une assertion lancée dans une vérification menée d’un seul coup à partir d’un point donné:
    définir un point vérificateur, c’est à dire qui va provoquer la vérification par le moteur de regex qu’un point qu’il est en train d’enregistrer dans un groupe n’est pas suivi du motif que l’on veut éviter dans la zône où est capté le motif en question.
    C’est la RE5 dans le code.
    \[(\w+)([^\]]*)\]'.'(((?!\[\\1.).)+)'.'(\[/\\1\])
    Mais je n’aime guère cette solution, je pense que ça donne plus de travail au moteur de regex.




    -----------------------------------------------





    Bon finalement, seules les chaÎnes du type '[buREAU]' et '[buTINER]' ne sont pas attrapées quand la balise de fin est '[/bu]' car la regex est telle qu’elle n’accepte de capturer entre deux balise qu’une chaîne ne ressemblant pas à une balise.
    Pour des chaines '[BOIS]', '[GEAI]', '[lune]' etc entre balises '[bu]...[/bu]' , il y aura capture, pour le reste non.

    Pour que la regex attrape quand même des motifs ressemblant à des balises, il faudrait qu’elle arrive à déterminer si un motif ressemblant est effectivement une balise ou non. Seule la connaissance de la liste des balises autorisées le permet.
    Car moi quand je regarde
    '[buvard]pour[bumi|999][buTINER][/bu]'
    qu’est ce qui me permet de décider que ’[bumi|999]’ doit être la balise de tête plutôt que ’[buTINER]’ ?

    D’ailleurs, sans référence à une liste des balises, c’est le même problème pour le webmaster d’un site: quand un connecté s’amuse à taper des chaînes ressemblant à des balises , comment fait il pour les détecter si ce n’est en usant de la liste des balises autorisées ?

    On devrait pouvoir écrire une RE qui arrive à tenir compte des noms de balises définis. Mais je verrai le problème plus tard, j’ai une petite fatigue là.

  6. #6
    Membre expérimenté
    Avatar de Rakken
    Homme Profil pro
    Inscrit en
    Août 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 257
    Points : 1 341
    Points
    1 341
    Par défaut
    Rebonjour et merci pour cette grande réponse !
    Je n'ai pas répondu plus tôt suite à un problème de connexion à internet, ceci étant, j'avais lu ton message au boulot et en y repensant au soir, j'ai eu "l'illumination", l'idée quoi.

    Mon problème venait du \\2 qui ne capturait pas correctement le début de ma balise, et ce que j'ai compris en étudiant les exemples de ton post, c'est que le truc à modifier était de "nourrir" correctement ce \\2.
    Donc j'ai refait ma regexp en partant de 0, avec l'idée de bien récupérer cette valeur,
    Dans mes divers exemples, en fait, mes types de balises pouvaient se résumer à deux cas :
    [test] et [test|
    Donc je me suis arrangé pour capturer ca. De fait, ayant mon \\2, le reste est venu tout seul.

    Bref, ca donne ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /(\[([\w]+)(\||\]))(.*)(\[\/\\2\])/U
    Quand au fait de savoir si une balise est ou pas une balise, ce n'est pas à la regexp de le savoir. Je fais ma capture et avec le preg_replace_callback j'envoi ce qui a été capturé à une méthode dédiée qui détecte quelle balise est envoyée et faire les remplacements si nécessaire.
    Si a l'intérieur de ma balise capturée, j'en ai d'autres, je refais l'appel récursivement.

    Ca à l'air de fonctionner nickel, et je ne suis pas encore tombé sur un exemple qui me plante.

    Voila, en tout cas, encore merci !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gérer les complexes avec <complex>
    Par Poutrator dans le forum Débuter
    Réponses: 5
    Dernier message: 01/07/2010, 15h10
  2. Gérer les clics sur les boutons
    Par cyberlewis dans le forum Windows
    Réponses: 4
    Dernier message: 08/02/2004, 15h34
  3. Comment gérer les espaces blancs?
    Par Lambo dans le forum XML/XSL et SOAP
    Réponses: 10
    Dernier message: 16/05/2003, 09h44
  4. [Documentation][XSLT][XSLFO]Les balises xslfo
    Par Lydiane dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 14/08/2002, 11h31
  5. gérer les jpg dans une fenetre directdraw???
    Par Anonymous dans le forum DirectX
    Réponses: 1
    Dernier message: 14/06/2002, 13h39

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