Aller au contenu

Petite expression régulière


MarvinLeRouge

Sujets conseillés

Salut,

Je cherche, dans une chaîne de caractère, à remlacer systématiquement toute sous-chaîne encadrée par des crochets par le contenu de la case de même index dans un tableau.

Exemple :

$remplace = array ("A" => "salut", "B" => "machin");
$chaine_depart = "[A] à toi, [b], ça va bien ?";

La chaîne résultat devrait être

salut à toi, machin, ça va bien ?

En fait, c'est l'utilisation du crochet comme repérage dans l'expression (comme symbole de séparation) qui me pose problème.

Merci

Lien vers le commentaire
Partager sur d’autres sites

$chaine_depart = "[A] à toi, [b], ça va bien ?";

$in= array
       (
'/(\[A\])/',
'/(\[b\])/'
);

$out = array
(
'salut',
'machin'
);
$chaine_finale=preg_replace($in, $out, $chaine_depart);

Dans ce goût là ?

Modifié par smile
Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Dans ce goût là, oui.

Il faudrait que la chaine de caractères entre crochets serve d'indice pour le tableau de remplacement : on remplace $X entre caractères crochets (quel que soit $X) par $tableau [$X].

Je ne sais pas si on peut faire ça directement par une expression, où s'il faut trouver un moyen de récupérer toutes les chaines entre crochets avec leurs coordonnées pour après les traiter dans une boucle.

NB : Et il faut faire attention au fait de s'arrêter à chaque fois dès le premier crochet fermant (afin de ne pas prendre par exemple 2 mots entre crochets plus ceux qui les séparent), ce que je ne sais pas exprimer en RegExp.

Modifié par MarvinLeRouge
Lien vers le commentaire
Partager sur d’autres sites

Bonsoir...enfin bonjour ;)

C'est là que les backreferences sont très utiles avec les expressions régulières :

$chaine_depart = "[A] a toi, [b], ca va bien ?";
function val_remplace($matches) {
$remplace = array ("A" => "salut", "B" => "machin");
// Remplace false par la valeur qui doit remplacer les balises ne se trouvant pas dans ton tableau
return array_key_exists($matches[1],$remplace) ? $remplace[$matches[1]] : false;
}
$chaine_finale=preg_replace_callback('/\[([a-z]+)\]/i', "val_remplace", $chaine_depart);

J'ai utilisé preg_replace_callback car il n'est pas possible d'utiliser une backreference (\\1 ou même \${1}) comme clé d'un tableau directement (avec preg_replace)... on touche au limites de l'interprétation des variables dans une chaîne de caractères...bref, tant mieux, cela permet de réaliser un test supplémentaire sur ce qui est trouvé ;)

La classe de caractères [a-z0-9] ne permettant pas le caractères espace, les expression entre cochets de plus d'un mots ne seront pas remplacées... bien entendu à toi de définir une classe de caractères qui te conviendra (par exemple autoriser les sous-tirets, tirets, ...)

P.S. Dans le code ci-dessus, [ b ] nest pas remplacé, car les clés de tableaux sont sensibles à la casse...il est tout à fait possible de faire un strtoupper lorsquon veut rechercher la clé dans le tableau et se dire que toutes les clés du tableaux doivent être en majuscules...par exemple)

Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Bonsoir ... enfin bonsoir :)

Merci beaucoup pour votre aide. J'ai réussi à atteindre mon but : je n'ai pas pu utiliser la fonction de callback indiquée parce qu'en l'occurence on est dans un objet et ça semble poser un pb, mais ce n'est pas grave.

J'ai simplement trouvé un masque suffisament tolérant pour mes noms de variables (j'ai pris ([a-z0-9\-\_]+)) et j'ai même fait ma petite fonction récursive pour faire les remplacements dans des tableaux à n dimensions.

Modifié par MarvinLeRouge
Lien vers le commentaire
Partager sur d’autres sites

Merci beaucoup pour votre aide. J'ai réussi à atteindre mon but : je n'ai pas pu utiliser la fonction de callback indiquée parce qu'en l'occurence on est dans un objet et ça semble poser un pb, mais ce n'est pas grave.

<{POST_SNAPBACK}>

Tu peux préciser un peux plus le problème (un exemple)...parce que si c'est un objet qui est le subject de la fonction preg_replace ou preg_replace_callback ce n'est pas un problème... à condition que la propriété de l'objet que tu souhaites traîter soit de type chaîne de caractères (string).

Merci d'avance.

Lien vers le commentaire
Partager sur d’autres sites

On est dans un objet, qui est instancié, la chaîne à traiter est un paramètre passé à une méthode de l'objet (mais pas une proriété de l'objet), et le tableau contenant les remplacement est lui une propriété de l'objet.

(Oui un peu tordu je suis d'accord)

Si on indique comme fonction de callback une méthode de l'objet, ça ne semble pas déclencher quoi que ce soit (pas d'erreur non plus d'ailleurs). Et si la fonction est externe à l'objet, ça complique le passage de paramètres.

J'ai donc opté pour un appel à preg_match_all, et une boucle de traitement sur les résultats fournis.

Lien vers le commentaire
Partager sur d’autres sites

Si j'ai bien compris, ton cas le code donnerait ceci avec un callback:

<?php
class Sample {
 var $remplace = array ("A" => "salut", "B" => "machin");
 
 function SampleMethod($chaine_depart) {
   return preg_replace_callback('/\[([a-z]+)\]/i', array(&$this, '_remplace'), $chaine_depart);
 }

 function _remplace($matches) {
   return array_key_exists($matches[1],$this->remplace) ? $this->remplace[$matches[1]] : false;
 }
}

$sampleInstance = new Sample();
echo $sampleInstance->SampleMethod("[A] à toi, [B], ça va bien ?");
?>

C'est un usage intéressant du type callback, pour appeler la méthode d'une classe on utilise cette syntaxe :

array(&$obj, 'user_function')

Donc lorsque la méthode doit être appelée en callback à l'intérieur de la class, il suffit d'utiliser &$this (cela représente l'instance de l'objet par référence...je ne t'apprend rien je pense ;)) et le tour est joué.

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...