8791 sujets

Développement web côté serveur, CMS

Bonjour tout le monde

Je cherche une regex PHP capable de détecter une sous-chaine dans une chaine et de supprimer des balises encadrantes.

Application :

$chaine =

<table>
<tr><td>AA</td><td>BB</td><td>CC</td></tr>
<tr><td>DD</td><td>EE</td><td>FF</td></tr>
</table>


$souschaine = FF

Je voudrais supprimer toute la < tr > contenant FF pour obtenir ça :

<table>
<tr><td>AA</td><td>BB</td><td>CC</td></tr>
</table>

... où toute la rangée a été virée.

Un spécialiste des regex dans les environs ???
Salut,

Tu peux simplement faire ça :

echo preg_replace( '#<tr>.*' . $souschaine . '.*</tr>#U', '', $chaine );


Mais je ne sais pas à quel point ça doit être dynamique au niveau des balises ...
Agylus a écrit :
Salut,

Tu peux simplement faire ça :

echo preg_replace( '#<tr>.*' . $souschaine . '.*</tr>#U', '', $chaine );


Mais je ne sais pas à quel point ça doit être dynamique au niveau des balises ...


Bah non, c'est juste l'inverse que je veux Smiley smile
echo preg_replace( '#<tr>.*' . $souschaine . '.*</tr>#U', 'aaa', $chaine );

donne
<table>aaa</table>
Donc en plus ça vite TOUTES les < tr >
Modifié par Arsene (30 Jul 2009 - 19:53)
Pas dans les tests que j'avais fait.

Tu peux nous passer exactement le code que tu as ? ($chaine et $souschaine)
Non, c'est un peu trop compliqué, ce sont des var PHP qui dépendent de l'environnement.
En gros je récupère la structure de table ($trdate = <tr> des dates) d'un fichier temp.txt par file_get_contents, ensuite la var $rechdate est déterminée dynamiquement.

J'ai donc en gros qqchose comme ça

$trdate =
<tr><td>Nom1</td><td>30/07/2009</td></tr>
<tr><td>Nom2</td><td>3/08/2009</td></tr>
<tr><td>Nom3</td><td>15/08/2009</td></tr>


A retraiter avant injection dans la balise <table>

Si $rechdate='3/08/2009';

Alors je veux obtenir
<tr><td>Nom1</td><td>30/07/2009</td></tr>
<tr><td>Nom3</td><td>15/08/2009</td></tr>


(au fait non seulement t'es pas en vacances mais en plus tu bosses aussi à des heures indues Smiley cligne )

Edit : idée soudaine... c'est peut-être dû à mes slashes qu'il faudrait échapper ? genre \/
Modifié par Arsene (30 Jul 2009 - 21:10)
Les slashes sont à échapper seulement si tu les utilises comme délimiteur, sinon il ne devrait pas y avoir de soucis.

Je viens d'essayer de mon côté, et bizarrement ça fonctionne :

$chaine = '<table><tr><td>Nom1</td><td>30/07/2009</td></tr> 
<tr><td>Nom2</td><td>3/08/2009</td></tr> 
<tr><td>Nom3</td><td>15/08/2009</td></tr></table>';

$souschaine = '3/08/2009';

echo preg_replace( '#<tr>.*' . $souschaine . '.*</tr>#U', '', $chaine );

/*
Afffiche :

<table><tr><td>Nom1</td><td>30/07/2009</td></tr> 
 
<tr><td>Nom3</td><td>15/08/2009</td></tr></table>
*/

Donc tu dois avoir quelque chose de différent de ce que je peux tester.
Sinon essaie toujours de rajouter un preg_quote() autour de $souschaine, mais je doute que ça change grand chose.

(J'ai déjà pris mes vacances. Smiley langue )
Aaaaarrrrgh je meurs


Ton code copié-collé sur Mac ne marche pas
Copié-collé sur PC il marche ;-(

Merci pour ton aide et bonne soirée

(rectif: ok sous OSX mais pas sous OS9)
Modifié par Arsene (30 Jul 2009 - 22:23)
Modérateur
Salut tout le monde,

Comme les motifs sont à peu près de la même équivalence, as tu besoin d'une RegEx ? As tu essayé de voir avec str_replace ou strtr ? Je peux peut être me tromper.

++
Non, les contenus des <tr> peuvent être très différents, là j'ai simplifié pour l'explication. J'ai donc besoin d'une fonction récursive pour traiter tout ce qui se trouve entre <tr> et </tr>.

Question à Agylus :

La regex dit : tout ce qui est a partir de (<tr>), quoi que soit (.*), jusqu'à ($souschaine), suivi de n'importe quoi (.*), jusqu'à (</tr>) en mode non-gourmand (U) doit être supprimé, c'est ça ?
C'est vrai que c'est simple. Mais pourquoi ne pas utiliser (e) qui sert aux références arrières à partir de la var ? C'est sûrement une question idiote mais les syntaxes de regex c'est du dur à avaler Smiley smile
Modifié par Arsene (30 Jul 2009 - 23:33)
Salut Arsene Smiley biggrin ,

Il faut effectivement échapper les slashes, des </tr> mais aussi de la date donc, il faut premièrement remplacer dans ta sous chaine les / par de \/.

Ensuite il faut prendre en compte les autres caractères entre la date et les <tr>, tu peux utiliser .* sinon comme ça :
/<tr>.*3\/08\/2009.*<\/tr>/


Tu peux essayer avec l'outil de Nolem, qui marche super http://www.lumadis.be/regex/test_regex.php !

Edit : http://lumadis.be/regex/test_regex.php?id=219 super cette fonction Nolem!
Modifié par matmat (30 Jul 2009 - 23:39)
Modérateur
Logiquement dans un preg_replace, il peut y avoir des parenthèses capturantes. Si ce n'est pas le cas, c'est tout le motif complet ($0) qui sera remplacé. En reprenant le motif de notre ami Agylus, je crois que ce serait plutôt ceci : Smiley murf


$chaine = '<table><tr><td>Nom1</td><td>30/07/2009</td></tr>  
<tr><td>Nom2</td><td>3/08/2009</td></tr>  
<tr><td>Nom3</td><td>15/08/2009</td></tr></table>'; 
 
$souschaine = '3\/08\/2009'; 
$pattern =  '#<tr>(.*' . $souschaine . '.*)<\/tr>#U';
echo preg_replace($pattern, '', $chaine );


matmat => De rien Smiley smile
Modifié par Nolem (30 Jul 2009 - 23:48)
Alors les gars, avec ou sans échappement c'est strictement pareil, j'ai essayé les deux et ça donne la même chose. Hier soir j'ai effectivement utilisé l'écriture de Nolem, mais celle d'Agylus est équivalente en terme de résultat.
Nolem je connaissais ton outil que j'utilise de tps en tps mais j'ignorais que c'était toi. Reeeeeeeespect Smiley cligne
Modifié par Arsene (31 Jul 2009 - 10:48)
Question à Agylus :

La regex dit : tout ce qui est a partir de (<tr>), quoi que soit (.*), jusqu'à ($souschaine), suivi de n'importe quoi (.*), jusqu'à (</tr>) en mode non-gourmand (U) doit être supprimé, c'est ça ?
Exactement. Smiley smile

[quote=Arsene]C'est vrai que c'est simple. Mais pourquoi ne pas utiliser (e) qui sert aux références arrières à partir de la var ? C'est sûrement une question idiote mais les syntaxes de regex c'est du dur à avaler Smiley smile
Le modificateur "e" ne sert pas aux références arrières, il force la fonction à traiter la chaine de remplacement comme du code PHP à exécuter.
Exemple :
$chaine = 'truc';
echo preg_replace( '#(.*)#e', "('$1' == 'truc') ? '$1 muche' : '$1'", $chaine );
// Affiche "truc muche"


Et puis comme je disais plus haut concernant l'échappement, ça ne sert que lorsque l'on utiliser le slash comme délimiteur ...
Modérateur
Agylus a écrit :
...ça ne sert que lorsque l'on utiliser le slash comme délimiteur ...


Ah oui exact, oups. J'ai eu un doute. Smiley confused

Arsene a écrit :
Nolem je connaissais ton outil que j'utilise de tps en tps mais j'ignorais que c'était toi. Reeeeeeeespect


Je suis ravis que tu me fasses cette éloge et bien que je vois comment est à peu près le script, ce n'est pas moi le créateur de cet outil. L'idée n'est pas bête du tout.
De retour avec une question existentielle.
J'ai dû, après bien des heures de tests pour en arriver là, faire un
$trdate = str_replace("</tr><tr>","</tr> \n <tr>",$trdate);

pour que cette s... de regex daigne fonctionner correctement dans tous les cas de figure. Apparemment le fait de garder les balises collées empêchait que ça marche.
En fait les exemples donnés ici fonctionnaient parce que la var contenant les <tr> était incrémentée.
Quelqu'un peut m'expliquer pourquoi ?