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 :

Regex répétée dans chaine BBCode [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre habitué Avatar de DiDieuh
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2009
    Messages : 111
    Points : 141
    Points
    141
    Par défaut Regex répétée dans chaine BBCode
    Bonjour à tous,

    Reprenant le principe du BBCode je suis en train de mettre en place un petit formulaire d'édition avec quelques mises en formes.Cependant, j'ai constaté lorsque je plaçais deux fois la même balise, ça remplaçait qu'une seule fois.
    Explication :
    -Si dans le textarea je mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     [tab][tab]MONTEXTE[/tab][/tab]
    -Il est transformé par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $texte = preg_replace('#\[tab\](.*)\[/tab\]#Usi', '<span style="margin-left:4em">$1</span>', $texte);
    - Et renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <span style="margin-left:4em">[tab]zezadaz</span>[/tab]
    J'aimerai savoir ou peut se trouver mon erreur car au final ça le fait pour toutes les balises si je "spam" un peu la même sur le même texte.

    Merci d'avance,
    DiDieuh
    DiDi

  2. #2
    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
    Bonsoir,



    $texte = 'kkkkkk[tab][tab]MONTEXTE[/tab][/tab]gggggg'

    RE = '#\[tab\](.*)\[/tab\]#Usi'
    RE = '#\[tab\](.*)\[/tab\]#Usi'




    Avec le coupe-faim U, la RE matche avec
    une sous-chaîne dans $texte:
    'kkkkkk[tab][tab]MONTEXTE[/tab][/tab]gggggg'
    'kkkkkk[tab][tab]MONTEXTE[/tab][/tab]gggggg'

    Donc le groupe (.*) capture
    '[tab]MONTEXTE'




    En remplaçant $1 dans '<span style="margin-left:4em">$1</span>'
    par '[tab]MONTEXTE'
    on obtient
    '<span style="margin-left:4em">[tab]MONTEXTE</span>'




    Cette chaîne est la remplaçante de la sous-chaîne matchante:
    'kkkkkk[tab][tab]MONTEXTE[/tab][/tab]gggggg'

    Ce qui donne:
    'kkkkkk<span style="margin-left:4em">[tab]MONTEXTE</span>[/tab]gggggg'



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


    Le problème maintenant est de savoir ce que tu veux obtenir comme résultat.


    Si tu veux simplement obtenir
    '<span style="margin-left:4em">MONTEXTE</span>'
    à partir de '[tab][tab]MONTEXTE[/tab][/tab]' uniquement
    il faut écrire
    RE = '#\[tab]\[tab](.*)\[/tab]\[/tab]#Usi'



    Si tu veux obtenir
    '<span style="margin-left:4em">MONTEXTE</span>'
    aussi bien
    à partir de '[tab][tab]MONTEXTE[/tab][/tab]'
    que de '[tab]MONTEXTE[/tab]'
    il faut employer preg_replace_callback() et une assertion conditionnelle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def $fs(m):
        return '<span style="margin-left:4em">'+m.group(2)+'</span>'
     
    $texte = preg_replace_callback('#\[tab](\[tab])?(.*?)(?(1)\[/tab])\[/tab]#Usi',$fs,$texte);



    Attention, mon langage est Python et je ne transcris peut être pas correctement tout.
    Ma fonction fs() n’a sans doute pas une mine très PHP-orthodoxe, par exemple.

  3. #3
    Membre habitué Avatar de DiDieuh
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2009
    Messages : 111
    Points : 141
    Points
    141
    Par défaut
    Bonjour à toi, et déjà merci.

    Pour la syntaxe Pythonienne pas de soucis j'en fais régulièrement donc pour retranscrire ça va le faire.
    En fait ce que je souhaite obtenir à la fin, c'est que pour chaque balise, l'effet soit appliqué. En gros, si l'utilisateur place n balises [tab], qu'il ai n fois l'effet de la balise, pour qu'il puisse décaler son texte comme il veut en fait.

    Merci d'avance,
    DiDi
    DiDi

  4. #4
    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
    Comme tu connais Python, j’ai résolu le problème en Python , tu transcriras facilement.

    Je ne connais pas de possibilité en Python de rappeler dans une référence arrière le nombre de sous-groupes capturés dans un groupe capturé antérieur, et cela m’étonnerait que ça existe en PHP.
    En clair, je ne connais pas de possibilité d’écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RE = ’((?:\[tab]){1,})(.+?)((\[/tab]){n})
    où n serait le nombre de ([tab]) détectés. Cela poserait d’ailleurs un problème supplémentaire: le groupe (.+?) serait le n+2 ième.



    Je suis donc passé par une fonction de remplacement, je n’ai pas trouvé autre chose:

    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
    import re
     
    pat = re.compile('((?:\[tab])+)(.*?)((?:\[/tab])+)')
     
    def ar(m):   # ar = analyse et retourne
        cnt1 = m.group(1).count('[tab]')
        cnt3 = m.group(3).count('[/tab]')
        if cnt1==cnt3:
            ret = m.group(2)
            for i in xrange(cnt1):
                ret = '<span style="margin-left:4em">'+ret+'</span>'
            return ret
        else:
            raw_input('Probleme: les nombres de [tab] et de [/tab] autour de la chaine\m'\
                      +m.group(2)+' sont differents')
     
    texte = 'atlantique [tab]MONTEXTE[/tab] orangeraie'
    print pat.sub(ar,texte)
    print
    texte = 'kkkkkk[tab][tab]MONTEXTE[/tab][/tab]gggggg'
    print ar(pat.search(texte))

    résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    atlantique <span style="margin-left:4em">MONTEXTE</span> orangeraie
     
    <span style="margin-left:4em"><span style="margin-left:4em">MONTEXTE</span></span>




    Si on ne se préoccupe pas de vérifier qu’il y a le même nombre de [tab] avant et de [/tab] après:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    patfast = re.compile('((?:\[tab])+)(.*?)(?:\[/tab])+')
    def hop(m):
        ret = m.group(2)
        for i in xrange(m.group(1).count('[tab]')):
            ret = '<span style="margin-left:4em">'+ret+'</span>'
        return ret
    texte = 'kkkkkk[tab][tab]MONTEXTE[/tab][/tab]gggggg'
    print patfast.sub(hop,texte)


    Je ne vois pas de moyen d’obtenir le nombre de sous-motifs [tab] autrement qu’en les comptant dans le premier groupe capturé, je crois qu’on est donc obligé d’en passer par une fonction de remplacement.

    En PHP, cela oblige à utiliser preg_replace_callback







    En PHP il existe un outil qui, je crois, n’existe pas en Python : les masques récursifs. Peut être pourrait il être utilisé un tel masque pour ce problème. Mais je n’ai pas encore lu complétement la page qui leur est consacrée
    http://fr2.php.net/manual/fr/regexp.....recursive.php
    et pas encore compris comment fonctionnent les masques récursifs.

  5. #5
    Membre habitué Avatar de DiDieuh
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    111
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2009
    Messages : 111
    Points : 141
    Points
    141
    Par défaut
    OK merci encore une fois ! Je test un peu tout ça et je te redis
    DiDi

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 11/06/2012, 20h15
  2. [C#] String Regex Position dans une chaine de caratère correspondant à un regex.
    Par jpbelmondo59 dans le forum Développement Windows
    Réponses: 1
    Dernier message: 09/06/2011, 13h41
  3. Réponses: 5
    Dernier message: 16/10/2010, 02h28
  4. recherche de caractères non_lettres dans chaine
    Par niconoe dans le forum Requêtes
    Réponses: 4
    Dernier message: 12/09/2005, 08h54
  5. [Firebird]position sous-chaine dans chaine
    Par rahan15 dans le forum SQL
    Réponses: 4
    Dernier message: 10/09/2005, 12h14

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