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 :

Capture arguments d'une fonction [RegEx]


Sujet :

Langage PHP

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Capture arguments d'une fonction
    Bonjour à tous,

    Je dois capturer les différents arguments passé à une fonction.
    Il m'est donnée une chaine brut en argument, ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $var = "\$arg1, \$arg.1, 'd'.'e', 'z', 'd,\\'e'";
    Le but final, est d'obtenir un tableau contenant les différents arguments, dans l'exemple ci-dessus:
    - $arg1
    - $arg.1
    - 'd'.'e'
    etc..

    Pour regler le problème lié aux caractères échappés, mais aussi celui
    lié au différents espaces, je me simplifie la vie en les supprimant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $var = str_replace(array("\t", "\n", "\r", "\x20"), array(), $var);
    $var = str_replace(array('\\\'', '\\"'), array(), $var);
    N'arrivant pas à solutionner mon problème, j'ai tenté de passer par un algorithme:
    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
     
    $pos_b = $pos_a = 0;
    $arg = array();
     
    for( $i=0; $i<strlen($var); $i++ )
    {
        if( $var[$i] === "'" )
        {
            if( $in )
            {
                $in = false;
                $pos_a = $i+1;
     
                if( $pos_b > 0 )
                   $pos_b -= 1;
     
                $arg[] = substr($var, $pos_b, $pos_a-$pos_b);
            }
            else 
            {
               $in = true;
               $pos_b = $i;
            } 
         }
    }
    Exemple d'ouput de $arg avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $var = "'xd',    'd,\\'e',    '2'.'e',     '3,'.\$s,    5.'e'";
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Array
    (
        [0] => 'xd',
        [1] => ,'d,e'
        [2] => ,'2'
        [3] => .'e'
        [4] => ,'3,'
        [5] => .'e'
    )
    Les double quotes n'ont pas été pris en compte (titre d'exemple).
    Le probleme majeur reste la concaténation avec un num..

    Avez-vous une solution via des regex (le fait d'etre entre des quotes m'intrigue un peu) ?

    J'avais essayé de passer par preg_split("#[']?.*[^'],[^'].*[']?#U", $var), mais sans resultat =(.

  2. #2
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Bonsoir,

    Je peux sortir un truc comme ça, qui marche avec tes deux exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <?php
    $myString = "'xd',    'd,\\'e',    '2'.'e',     '3,'.\$s,    5.'e'";
    $pattern = '# (\S+) (?: , \s+ | $) #x';
     
    preg_match_all($pattern, $myString, $matches);
     
    $captures = $matches[1];
    foreach($captures as $value) 
    	print $value ."\n";
    Mais c'est quand même vachement dépendant de l'entrée.
    Dans ce cas, j'ai considéré que le séparateur était une virgule suivie d'espaces. Mais est-ce toujours le cas ?

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Tout d'abord merci de m'avoir répondu si rapidement =)

    Désolé pour les exemples que j'ai donnée, j'ai séparé les différents arguments afin de bien les montrer aux membres du forum.

    En faite la chaine qui me sera donnée vient directement de code PHP (qui varie), ma regex devra donc être compatible avec les différentes syntaxes que PHP supporte. Cependant je ne prend pas en compte le support des syntaxes multilignes (mais si ça le fait je suis preneur aussi =)).

    Voilà un exemple qui montre les différents cas particuliers à supporter:
    'a '.', ', 5.'e','x'.CONSTANTE,5.$variable/2,(($x % 2) ? 2 : 3)

    On pourrait donc définir les arguments de cette façon: Un argument est identifié comme tel si elle séparé d'une virgule qui n'est pas entourée de quote, ou si c'est le dernier argument, s'il est précédé d'une parenthèse fermante ). Je rappelle que j'ai tout l'appelle qui m'est donnée, exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if( preg_match('#...#', $v, $d) ) ...
    #On me donne ça en chaine, j'arrive a aller jusqu'au preg_match()
    # car je fais en faite une recherche sur des fonctions ciblé, dans
    # du code php [je veux lister tout les arguments passés a une/des
    # fonctions dans mes différents codes en faite]
    Donc soit je passe par une regex, soit il me faudrait un algorithme utilisé directement par un langage, ou un editeur (comment la coloration syntaxique fait-t-elle pour coloré d'une couleur différentes chaque arguments, comment elle fait pour savoir si c'est un argument etc..) histoire de voire comment le tout fonctionne en gros.

    Je vais commencer à effectuer des recherches vers différents scripts de coloration syntaxique tel que Geshi, je vous en ferais part par la suite.

    Si vous avez des informations qui pourrait m'aider n'hesitez pas.

  4. #4
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Que contiendra $v ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $myString = "'a '.', ', 5.'e','x'.CONSTANTE, 5.$variable/2, (($x % 2) ? 2 : 3)";
    ou déjà un peu plus pratique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $myString = "'a '.', ', 5.'e','x'.CONSTANTE, 5.\$variable/2, ((\$x % 2) ? 2 : 3)";
    J'ai plusieurs problèmes, qui se résument à l'interaction des quotes et des virgules.
    Prenons l'exemple de cet argument : 'a '.'
    Comment identifier le guillemet qui fait partie de la chaîne de ceux qui la délimitent ?
    N'est-il pas possible que tu les échappe au moment de l'alimentation de ta variable $v ?

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par shelly Voir le message
    Voilà un exemple qui montre les différents cas particuliers à supporter:
    'a '.', ', 5.'e','x'.CONSTANTE,5.$variable/2,(($x % 2) ? 2 : 3)
    J'ai déjà vu des commentaires dans les paramètres d'appel de fonction. Il y a peut-être aussi d'autres désagréments dans ce style.

    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
     
    <pre>
    <?php
     
    $regex = '@/\*[^*]*\*/|'; // enlever les commentaires
    $regex.= '((?:(?:\'(?:\\\{2}|[\\\]\'|[^\'])*\'|'; // intégriter simple-quote
    $regex.= '"(?:\\\{2}|[\\\]\'|[^"])*"|'; // intégriter double-quote
    $regex.= '[^,\s"\']+)\s*)+)|'; // intégriter non-quote
    $regex.= '\s*,\s*@s'; // délimiter sur la virgule avec possibles blancs
     
    $options = PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY;
     
    $params[] = "\$arg1, \$arg.1, 'd'.'e', 'z', 'd,\\'e'";
    $params[] = "'xd',    'd,\\'e',    '2'.'e',     '3,'.\$s,    5.'e'";
    $params[] = '"a ".", ",5."e","x".CONSTANTE,5.$variable/2,(($x % 2) ? 2 : 3)';
    $params[] = "'a '.', ',/*5.'e','x'.CONSTANTE,*/5.\$variable / 2 ,
                 ((\$x % 2) ? 2 : 3)";
     
    foreach ($params as $param) {
      $matches = preg_split($regex, $param, -1, $options);
      print_r($matches);
    }
     
    ?>
    </pre>
    Le tokenizer offre peut-être une meilleure précision.

    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
     
    <pre>
    <?php
     
    $params[] = "\$arg1, \$arg.1, 'd'.'e', 'z', 'd,\\'e'";
    $params[] = "'xd',    'd,\\'e',    '2'.'e',     '3,'.\$s,    5.'e'";
    $params[] = '"a ".", ",5."e","x".CONSTANTE,5.$variable/2,(($x % 2) ? 2 : 3)';
    $params[] = "'a '.', ',/*5.'e','x'.CONSTANTE,*/5.\$variable / 2 ,
                 ((\$x % 2) ? 2 : 3)";
     
    $skip = array(T_OPEN_TAG, T_COMMENT, T_WHITESPACE, T_CLOSE_TAG);
     
    foreach ($params as $param) {
      $tokens = token_get_all('<?php' . $param . '?>');
      $matches = array();
      $match = '';
      foreach ($tokens as $token) {
        if (is_array($token)) {
          if (!in_array($token[0], $skip) && strtolower($token[1]) != 'php') {
            $match.= $token[1];
          }
        }
        else if ($token != ',') $match.= $token;
        else {
          $matches[] = $match;
          $match = '';
        }
      }
      $matches[] = $match; // le dernier paramètre
      print_r($matches);
    }
     
    ?>
    </pre>

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Ah ! Le tokenizer voilà exactement ce qu'il me fallait, je vais m'orienté vers cette voie merci.

    J'avais solutionné le probleme en passant par un algorithme, je commençait par parcourir ma chaine, et tout ce qui avait entre les quotes (en ne prenant pas en compte les \" et \'), je supprimais les caracteres .,"'. Ensuite je faisais un explode des "." et j'obtenais la liste des arguments.

    Merci !

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

Discussions similaires

  1. [VBA-E] Lister les arguments d'une fonction
    Par laloune dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 26/02/2006, 12h04
  2. Récupération d'arguments sur une fonction
    Par p0Kep0K dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 21/09/2005, 09h17
  3. premier argument d'une fonction
    Par Ickou dans le forum Langage
    Réponses: 3
    Dernier message: 10/09/2005, 14h17
  4. une url comme argument d'une fonction
    Par khayyam90 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 18/10/2004, 20h15
  5. passer FILE* en argument d une fonction
    Par Monsieur_Manu dans le forum C
    Réponses: 9
    Dernier message: 10/04/2003, 17h56

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