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 :

Problème de balises /paranthèses imbriquée [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut Problème de balises /paranthèses imbriquée
    Bonjour à tous! Je vais illustrer mon problème par un exemple (avec des parethèses, mais ça pourrai aussi être des balises).

    Texte: 6*(1+(4-2)/(sin(x)+(4+7)))-9*(2^(3-2)+1)
    But: Rechercher les groupes de paranthèse:
    c'est-à-dire qu'il me donne:
    1+(4-2)/(sin(x)+(4+7)) et 2^(3-2)+1
    C'est à dire que dès qu'il voit l'ouverture d'une paranthèse il va chercher celle qui se ferme (et qui lui corresond) et retourne le contenu.

    Il y a-t-il un moyen de faire ça avec des regexp ou le mieux et de programmer le truc sans regexp?

    Merci d'avance!

    PS: Si je suis pas clair, n'hésitez pas à me le faire savoir...

  2. #2
    Membre habitué Avatar de daniel61
    Inscrit en
    Décembre 2006
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 139
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par bugmenot
    Texte: 6*(1+(4-2)/(sin(x)+(4+7)))-9*(2^(3-2)+1)
    But: Rechercher les groupes de paranthèse:
    c'est-à-dire qu'il me donne:
    1+(4-2)/(sin(x)+(4+7)) et 2^(3-2)+1
    C'est à dire que dès qu'il voit l'ouverture d'une paranthèse il va chercher celle qui se ferme (et qui lui corresond) et retourne le contenu.
    de mémoire, il y a un exemple sur php.net comme sur pcre.org dans la partie "recursive patterns", masques récursifs en français. moi j'écrirais preg_match_all('#[(]((?:[^()]+|(?R))*)[)]#',....); pas du tout testé.

    bon, j'ai l'impression de t'apporter + de questions que de réponses... si tu as des questions supplémentaires, n'hésites pas, mes neurones déficiantes arriveront peut-être à formuler quelque chose d'intelligent.

    ouais, aussi bien trouver la page sur php.net...
    http://www.php.net/manual/fr/referen...ern.syntax.php
    vers le bas sous "masques récursifs" tu as des explications et la regex est bien là '#\( ( (?>[^()]+) | (?R) )* \)#x' et elle a une drôle de tête... pour capturer en \\1 sans la première parenthèse ouvrante et la dernière parenthèse fermante, tu peux la transformer en '#\( ( (?: (?>[^()]+) | (?R) )* ) \)#x' et elle a toujours une drôle de tête, m'enfin ça vient de la doc officielle.

    l'option x permet d'ajouter des espaces pour aérer l'expression, mais en même temps elle enlève la possibilité d'utiliser l'espace comme pattern... et c'est souvant pratique l'espace, dans du html notamment.

    (?>...) est un masque unique, un genre d'ancrage dans le vide, dans ce cas si (?>[^()]+) ne sortira pas du masque unique tant et aussi longtemps qu'il n'y aura pas de caractère ( ou ) de rencontré dans la chaine source. en théorie c'est supposé accélérer les temps de traitement, dans la pratique mes tests m'ont plutôt donner de sévève ralentissements.

    |(?R) est la récursive, qui répétera du pattern précédent (?>...) jusqu'à ce qui succède (?R). toutes les formes récursives doivent en fait être vues comme des sous-routines. ici la particularité de |(?R) est d'être un genre de do-while... et le do-while ce fait de \( à \)...

    des questions?

  3. #3
    Expert éminent sénior

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Points : 17 778
    Points
    17 778
    Par défaut
    Pour l'idée de faire sans voilà ce que je vous propose :
    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
    $texte = "6*(1+(4-2)/(sin(x)+(4+7)))-9*(2^(3-2)+1)";
     
    function smart_split($texte) {
        $parentheses = array();
        $pile = array();
        $nb = 0;
        for ($i = 0, $l = strlen($texte); $i < $l; $i++) {
            if ($texte[$i] == '(') {
                array_push($pile, $nb++);
                $parentheses[] = array($i);
            } else if ($texte[$i] == ')') {
                $parentheses[array_pop($pile)][1] = $i;
            }
        }
        return $parentheses;
    }
     
    foreach (smart_split($texte) as $partie) {
        echo substr($texte, $partie[0] + 1, $partie[1] - $partie[0] - 1) . '<br/>';
    }
    Le tableau renvoyé par smart_split étant de la forme :
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Array (
      0 => Array ( // Première parenthèse trouvée
        0 => position de la parenthèse ouvrante
        1 => position de la parenthèse fermante
      ),
      1 => Array ( // Deuxième parenthèse trouvée
        0 => position de la parenthèse ouvrante
        1 => position de la parenthèse fermante
      ),
     // ...
    )
    Résultat obtenu avec 6*(1+(4-2)/(sin(x)+(4+7)))-9*(2^(3-2)+1) :
    1+(4-2)/(sin(x)+(4+7))
    4-2
    sin(x)+(4+7)
    x
    4+7
    2^(3-2)+1
    3-2

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    merci pour a solution Regexp. C'est exactement ce que je cherchais (j'ai pas encre testé, mais ça devrait fonctionner au poil).

    EDIT: Bon je viens de tester et ça marche pas sous Python

    voila le code python (pour d'autre eventuelles interessé):

    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
     
    class MaskError(Exception):
             def __init__(self, value):
                 self.value = value
             def __str__(self):
                 return repr(self.value)
     
    def get_par(txt,delim=("(",")")):
        res=[]
        deb=-1
        k=0
        for x in enumerate(txt):
            if x[1]==delim[0]:
                k+=1
                if deb==-1: deb=x[0]
            if x[1]==delim[1]:
                k-=1
                if k<0 or deb==-1: raise MaskError, "too many closing delimiter"
                elif k==0:
                    res.append(txt[deb+1:x[0]])
                    deb=-1
        if k>0: raise MaskError, "too many opening delimiter"
        return res

  5. #5
    Membre habitué Avatar de daniel61
    Inscrit en
    Décembre 2006
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 139
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par bugmenot
    EDIT: Bon je viens de tester et ça marche pas sous Python
    les expressions régulières sous python ne supportent pas les récursives, par contre php supporte très bien les récursives et il y a d'autres différences entre python et php. ça aurait été gentil d'avoir dit que c'était pour python avant maintenant. dans le doute, j'ai testé les 3 expressions de mon message précédent sous plusieurs versions php sur différentes machines, et elles sont toutes les 3 fonctionnelles sous php... il aurait-été navrant qu'une expression sur le site même de pcre.org comme sur le site de php.net ne soit pas fonctionnelle.

  6. #6
    Membre éclairé Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Points : 718
    Points
    718
    Par défaut
    Ne cherche pas à le faire en 1 expression régulière, ce n'est pas possible. Il te faut une fonction (Il te faudrait une Pile pour le faire simplement donc un simple tableau suffit)

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    ben une regexp reste une regexp, donc préciser que c'était pour python n'aurait pas changer grand chose (mais je m'aprecois du contraire...). De plus je fais aussi du php et cette fonction m'intressait de toute façon. Donc ton tuyau n'a pas été si inutile que ça; merci d'ailleur pour le tuyau.

    Ne cherche pas à le faire en 1 expression régulière, ce n'est pas possible. Il te faut une fonction (Il te faudrait une Pile pour le faire simplement donc un simple tableau suffit)
    C'est gentil de voiloir aider, mais tu m'expliques l'utilité de ton message? On vient de dire plus haut que les regexp récursives ne fonctionnent pas sous python et en plus j'ai posté le prog pour le faire en non-regexp....

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

Discussions similaires

  1. Problème avec balise <a href="file></a>
    Par tissard dans le forum Balisage (X)HTML et validation W3C
    Réponses: 25
    Dernier message: 07/06/2006, 10h59
  2. balise form imbriquée
    Par amika dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 09/04/2006, 08h34
  3. Réponses: 2
    Dernier message: 11/01/2006, 15h49
  4. [RegEx] problème de balises
    Par Asarnil dans le forum Langage
    Réponses: 4
    Dernier message: 21/10/2004, 15h13
  5. problème avec une requête imbriquée
    Par jaimepasteevy dans le forum Langage SQL
    Réponses: 13
    Dernier message: 05/12/2003, 10h29

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