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 :

Remplacement par preg_replace [RegEx]


Sujet :

Langage PHP

  1. #1
    Invité
    Invité(e)
    Par défaut Remplacement par preg_replace
    Bonjour

    Je souhaiterais remplacer une expression par un autre dans un Define.
    En somme j'ai un define : DEFINE('NAME','christobale');
    Via preg_replace je souhaiterais remplacer "christobale" par autre chose dans la constante NAME.
    Je ne peux pas utiliser un simple str_replace car parmis toutes les constantes certaine peuvent avoir la même valeur.

    D'avance merci

  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
    Bonjour

    Il y a le lookbehind qui peut valider si quelque chose est avant la capture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $data = "DEFINE('NAME','christobale');";
    echo preg_replace('`(?<=DEFINE\(\'NAME\',\')christobale`si', 'changement',$data);
    Sauf que le lookbehind doit toujours être fixe en nombre de caractère à valider, donc pas de \s* par exemple.

    Il y a les débrouillards qui se contentent de capturer la partie à valider et de la reporter dans le remplacement grâce à \1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $data = "DEFINE('NAME','christobale');";
    echo preg_replace('`(DEFINE\(\'NAME\',\')christobale`si', '\1changement',$data);
    mais ça consomme plus de mémoire dû au backtracking.

    Depuis quelques versions il est possible de faire un reset de pattern avec \K que j'aime bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $data = "DEFINE('NAME','christobale');";
    echo preg_replace('`DEFINE\(\'NAME\',\'\Kchristobale`si', 'changement',$data);
    sauf qu’un seul \K par pattern fait du sens.

    si c'est du code PHP, il serait peut-être préférable d'utiliser la fonction token_get_all()

  3. #3
    Invité
    Invité(e)
    Par défaut
    daniel61, merci d'avoir répondu.
    Cependant je suis toujours dans le flou.
    Je ne sais pas trop quelle solution utiliser entre la deux et la trois.
    Surtout si l'une consomme trop de mémoire (mais dans quelle mesure ? De plus se sera une action plutôt rare.)
    Quant a la trois, j'ai bas saisie ta remarque (sauf qu’un seul \K par pattern fait du sens).
    Pour info c'est bien du PHP.

  4. #4
    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
    Désolé pour le flou.

    d'abord, plus de mémoire ne veut pas dire trop de mémoire. Si la technique te va, alors tout va.

    le \K est un lookbehind amélioré, tout ce qui est à gauche est une validation. Donc avoir 2 fois \K n'a pas beaucoup de sens puisque le premier \K sera à gauche du deuxième.

    L'ennui avec du code PHP, c'est possiblement contextuel. Par exemple sur le code 'test_code.php'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <div>DEFINE('NAME',17)</div>
    <?php
    DEFINE('NOM','daniel61');
    DEFINE ( 'NAME' , 'christobale') ;
    DEFINE('TROIS','quelques');
    $var = "DEFINE('NAME',true);";
    ?>
    Et que j'applique une expression régulière que je penserais correct
    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
    <?php
     
    header('Content-type: text/plain');
     
    $code = file_get_contents('test_code.php');
     
    $define = "'NAME'"; // nom de la constante à changer
    $remplacer = "'changement'";  // la nouvelle valeur
     
    $valeur = '(([\'"]).*?\2|[^\s)]+)'; // match ancienne valeur
    $regex = "`DEFINE\s*\(\s*$define\s*,\s*\K$valeur`si";
     
    echo preg_replace($regex, $remplacer, $code);
     
    ?>
    j'obtienderai
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <div>DEFINE('NAME','changement')</div>
    <?php
    DEFINE('NOM','daniel61');
    DEFINE ( 'NAME' , 'changement') ;
    DEFINE('TROIS','quelques');
    $var = "DEFINE('NAME','changement');";
    ?>
    soit 3 changements car l'expression ne pouvait connaître le contexte globale du contenu de variable comme du code HTML. Maintenant si ça ne peut se produire dans ton cas, ou si c'est les 3 changements qui sont désirés, alors tout va avec cette expression régulière.

    j'avais oublié à quel point le tokeniser était casse tête, par contre il offre une meilleure connaissance du contexte global, si c'est nécessaire
    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
    <?php
     
    $code = file_get_contents('test_code.php');
     
    $define = "'NAME'";  // nom de la constante à changer
    $remplacer = "'changement'";  // la nouvelle valeur
     
    $is_define = 0;
    $modifier = '';
     
    header('Content-type: text/plain');
     
    $tokens = token_get_all($code);
    foreach($tokens as $token) {
      if(is_string($token)) $modifier .= $token;
      else {                                     
        list($id, $texte, $ligne) = $token;
        if ($id != 375) { // T_WHITESPACE 
          if (!$is_define && strtolower($texte) == 'define') $is_define = 1; // DEFINE?
          else if ($is_define == 1 && $id == 315) { // 315 = T_CONSTANT_ENCAPSED_STRING
            if ($define == $texte) $is_define++;
            else $is_define = 0;
          } 
          else if ($is_define == 2) {
            $texte = $remplacer; // le remplacement
            $is_define = 0;
          }
          else $is_define = 0;
         }
        $modifier .= $texte;
      }
    }                            
    echo $modifier;
     
    ?>
    produira
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <div>DEFINE('NAME',17)</div>
    <?php
    DEFINE('NOM','daniel61');
    DEFINE ( 'NAME' , 'changement') ;
    DEFINE('TROIS','quelques');
    $var = "DEFINE('NAME',true);";
    ?>
    donc effectuera le changement sur le réel défine PHP. Mais encore là, si le premier code te va, alors tout va.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Merci infiniment pour ces éléments d'informations, c'est très instructif.
    La première solution me convient très bien, elle semble répondre a mon besoin.

    Par contre j'ai deux questions :

    1 - Dans ton regex tu as mis se caractère ( ` ) a quoi cela sert-il ?
    C'est la première foi que je le vois dans un code php.

    2 - Dans la doc php je peux passer un tableau en $pattern et en $replacement dans le preg_replace. Mais avec ton code j'y arrive pas.

    Merci infiniment pour ton aide.

  6. #6
    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 christobale Voir le message
    1 - Dans ton regex tu as mis se caractère ( ` ) a quoi cela sert-il ?
    C'est la première foi que je le vois dans un code php.
    Le premier caractère d'une expression régulière est le délimiteur pour séparer l'expression régulière des options à la fin. Ce délimiteur il est à ton choix, j'ai utilisé les options s (retour à la ligne non bloquante) et i (insensible à la case).

    Citation Envoyé par christobale Voir le message
    2 - Dans la doc php je peux passer un tableau en $pattern et en $replacement dans le preg_replace. Mais avec ton code j'y arrive pas.
    Montre la partie du code concerné si tu veux de l’aide sur ce point.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Donc voici ce que donne le code :
    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
     
    header('Content-type: text/plain');
    	$filename = file_get_contents('configuration.php');
     
    	$define = "'NOM_CLIENT'"; // nom de la constante à changer
    	$remplacer = "'CAPandCO'";  // la nouvelle valeur
     
    	$valeur = '(([\'"]).*?\2|[^\s)]+)'; // match ancienne valeur
    	$regex = '`DEFINE\s*\(\s*'.$define.'\s*,\s*\K'.$valeur.'`si';
     
    	$NewConfig = preg_replace($regex, $remplacer, $filename);
    	$handle = fopen('configuration.php', 'r+');
     
    	if ( is_writable ('configuration.php') and $handle !== FALSE ) 
    	{
    		//--- Copie du fichier avant modification
    		copy('configuration.php','configuration.'.date('Y-m-d H:i:s').'.'.$_SESSION['nom'].'-'.$_SESSION['prenom'].'.'.'bak');
     
    		//--- Ecriture dans le fichier
    		fwrite($handle,$NewConfig);
    		fclose($handle);
    	}
    	else
    	{
    		die('Impossible d\'écrire dans.');
    	}
     
    echo $NewConfig;
    J'aimerai donc pouvoir modifier plusieurs constante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $define = array("'NOM_CLIENT'","'PRENOM_CLIENT'","'TEL_CLIENT'"); // nom de la constante à changer
    $remplacer = array("'Toto'","'Truc Much'","'06.78.78.78.78'");  // la nouvelle valeur

  8. #8
    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
    Bonsoir

    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
    <?php
     
    header('Content-type: text/plain');
     
      $filename = file_get_contents('configuration.php');
     
      $defines = array("'NOM_CLIENT'","'PRENOM_CLIENT'","'TEL_CLIENT'"); // les constantes à changer
      $remplacer = array("'Toto'","'Truc Much'","'06.78.78.78.78'");  // les nouvelles valeurs
      $regex = array();
     
      $valeur = '(([\'"]).*?\2|[^\s)]+)'; // match anciennes valeurs
      foreach ($defines as $define) {
        $regex[] = '`DEFINE\s*\(\s*' . $define . '\s*,\s*\K' . $valeur . '`si';
      }
     
      $NewConfig =  preg_replace($regex, $remplacer, $filename);
     
      echo $NewConfig;
     
    ?>

  9. #9
    Invité
    Invité(e)
    Par défaut
    Bonjour et un très grand merci pour ton aide.
    Surtout ne change rien c'est tellement rare de trouver des personnes qui prenne le temps d'aider et d'expliquer.
    Encore milles merci.

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

Discussions similaires

  1. Remplacer foncton eregi_replace par preg_replace
    Par Amouna85 dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 10/10/2011, 16h40
  2. [RegEx] Remplacer ereg_replace par preg_replace
    Par mr_insane dans le forum Langage
    Réponses: 16
    Dernier message: 28/01/2011, 12h02
  3. [RegEx] Remplacer ereg_replace par preg_replace
    Par manuaparis dans le forum Langage
    Réponses: 2
    Dernier message: 26/12/2009, 18h38
  4. [XSLT] Remplacer par des caractères spéciaux
    Par OXyGN dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 29/07/2005, 18h30
  5. [JSTL] Mes variables ne sont pas remplacées par leur valeur
    Par thomine dans le forum Taglibs
    Réponses: 9
    Dernier message: 18/03/2005, 11h00

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