JeuWeb - Crée ton jeu par navigateur
Encore une regex... - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Encore une regex... (/showthread.php?tid=7107)

Pages : 1 2


Encore une regex... - php_addict - 12-08-2013

Bonjour

encore un petit problème de regex, et je ne comprends pas du tout pourquoi cela ne marche pas alors qu'il me semble que cela devrait le faire plutôt pas mal...



$text = '[p]<ok>[/p]';

$search = Array ( '0' => '#\[p\](.*)\[/p\]#isU');
$replace = Array ( '0' => htmlentities('$1') );

echo preg_replace($search, $replace, $text,-1,$count);

// affiche ceci:

<ok>

et comme debugage, le preg_replace semble détecter la chaine mais ne la remplace pas ($count)



$count=0;
$text = '[p]<ok>[/p]';

$search = Array ( '0' => '#\[p\](.*)\[/p\]#isU');
$replace = Array ( '0' => htmlentities('$1') );

echo preg_replace($search, $replace, $text,-1,$count);
echo ' $count = ' . $count;

// affiche ceci:

<ok> $count = 1

merci de m'avoir lu, je sais que les regex c'est pénible pour tout le monde...

un coup de pouce?


RE: Encore une regex... - Xenos - 12-08-2013

Salut,

raté, j'adore les regex, car je trouve le mécanisme très puissant :p

preg_replace remplace bien $search par $replace dans ta chaine $text, et $count reçoit bien le nombre de remplacements effectués.
Ta chaine d'entrée '#\[p\](.*)\[/p\]#isU' est cherchée, et trouvée. [p]<ok>[/p] est donc remplacé par htmlentities('$1').
Or, htmlentities est une fonction, non une chaine de caractères, donc elle est exécutée dès la ligne 5. $replace est donc un tableau qui à l'index 0 associe le résultat de htmlentities('$1'), qui doit être $1.
Donc, preg_replace reçoit:

preg_replace('#\[p\](.*)\[/p\]#isU', '$1', '[p]<ok>[/p]',-1,$count)

Et elle s'exécute bel et bien.
Si tu souhaites appliquer htmlentities à ce que la regex capture dans ses parenthèses, il te faut utiliser preg_replace_callback.

Code PHP :
<?php
$count
=0;
$text = '[p]<ok/>[/p]';

$search = Array ( '0' => '#\[p\](.*)\[/p\]#isU');

echo
preg_replace_callback($search,
function (
$p_matches)
{

//var_dump($p_matches);
//$p_matches = array (size=2)
// 0 => string '[p]<ok>[/p]' (length=11)
// 1 => string '<ok>' (length=4)

return htmlentities($p_matches[1]);
}
,
$text,-1,$count);
echo
' $count = ' . $count;

// affiche ceci:
// &lt;ok&gt; $count = 1

?>
Pour comprendre comment $p_matches fonctionne, fais quelques tests avec des chaînes plus complexes et avec des balises [p] imbriquées.


RE: Encore une regex... - Arnadus - 12-08-2013

Je comprends pas ce que tu veux faire. Elle fonctionne très bien ta regex, tu demandes à PHP d'aller te remplacer le contenu de ce qu'il y a entre les balises [p] et [\p] par... le même contenu.

Si tu veux juste remplacer les balises [p] de ton code par leur équivalent html, suffit de modifier un peu ton replace:

Code :
<?php
$text = '[p]<ok>[/p]';

$search  = Array ( '#\[p\](.*)\[/p\]#isU');
$replace = Array ( '<p>$1</p>' );

echo preg_replace($search, $replace, $text,-1,$count);
?>

mais bon, si tu veux uniquement faire du remplacement de balisage, utiliser un preg_replace est un peu too much.

Un simple str_replace suffirait.

Code :
<?php
$text = '[p]<ok>[/p]';


$search  = Array ( '[p]', '[/p]');
$replace = Array ( '<p>', '<\p>' );

echo str_replace($search, $replace, $text);
?>



RE: Encore une regex... - Xenos - 12-08-2013

Sauf que str_replace va remplacer [p]Balise non fermée par <p>Balise non fermée et bonjour les injections GUI \o/
Bon, avec <div> au lieu de <p>, ce serait encore pire...

Je pense que ce qu'il cherche à faire, c'est échapper les caractères HTML qui se trouvent uniquement entre les balises [p][/p], mais je me trompe peut-être.


RE: Encore une regex... - niahoo - 12-08-2013

php dispose d'un parser bbcode, tu réinventes la roue la Smile mais libre à toi


RE: Encore une regex... - Arnadus - 12-08-2013

+1 pour niahoo

Il existe une foullitude d'implémentation de BBcode sur la toile. Tu n'as qu'à choisir.


RE: Encore une regex... - niahoo - 12-08-2013

Je parle de l'extension officielle :

http://php.net/manual/fr/book.bbcode.php


RE: Encore une regex... - Arnadus - 12-08-2013

Oui je sais, j'avais compris. L'extension officielle en fait partie.


RE: Encore une regex... - php_addict - 12-08-2013

(12-08-2013, 11:25 AM)Xenos a écrit : raté, j'adore les regex, car je trouve le mécanisme très puissant :p

Smile , oui heureusement qu'il y a des codeurs qui aiment les regex Smile

Merci de ton aide, je ne suis pas certain d'avoir compris la nécessité d'un callback, mais ça fonctionne à merveille, merci !!!

(12-08-2013, 11:37 AM)Xenos a écrit : Je pense que ce qu'il cherche à faire, c'est échapper les caractères HTML qui se trouvent uniquement entre les balises [p][/p], mais je me trompe peut-être.

oui voilà...

(12-08-2013, 11:46 AM)niahoo a écrit : php dispose d'un parser bbcode, tu réinventes la roue la Smile mais libre à toi

(12-08-2013, 11:54 AM)Arnadus a écrit : Il existe une foullitude d'implémentation de BBcode sur la toile. Tu n'as qu'à choisir.

oui je sais bien, mais mon parseur de bbcode doit traiter des bbcodes très spéciaux, genre bbcode pour afficher un rapport, ou bien une coordonnée sur la carte, et d'autres bbcodes très atypiques...

en tout cas merci, cela fonctionne à merveille avec preg_replace_callback


RE: Encore une regex... - Xenos - 12-08-2013

Le callback est nécessaire. preg_replace ne fait qu'un remplacement littéral: la chaîne de caractères trouvées sera remplacée par la chaîne de caractères $replace, aux $1..$N près.
Dans ton cas, tu aimerais passer la chaîne trouvée à la fonction htmlentities, ce qui n'est pas possible en utilisant une chaîne de caractères $replace dans preg_replace, d'où la callback.

Si htmlentities avait pris, comme paramètre, un tableau $p_matches, la callback aurait pu être directement la fonction htmlentities. Mais ce n'est pas le cas, d'où la nécessité de passer par une callback intermédiaire, aka, une fonction perso (anonyme ici).