Précédent   Forum des professionnels en informatique > PHP > Langage > Regex
Regex Forum d'entraide sur les expressions rationnelles PHP. Avant de poster -> FAQ regex, Cours de regex et Sources de regex
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 18/03/2008, 09h30   #1
Invité de passage
 
Inscription : février 2008
Messages : 18
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 18
Points : 1
Points : 1
Par défaut Je recherche une chaîne qui ne contient pas une certaine chaîne

J'ai par exemple :

<strong><strong>mot1</strong>mot2</strong>

Je souhaite écrire une expression régulière qui va rechercher 2 <strong> où entre les 2 il n'y a pas de </strong> afin d'en supprimer un.

Même chose pour 2 </strong> où entre les 2 il n'y a pas de <strong>

Mais je ne sais pas comment lui dire trouve moi la chaine qui contient <strong>(.*)[pas la chaîne "</strong>"](.*)<strong>

Merci d'avance pour votre aide.
johann51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/03/2008, 09h49   #2
Invité de passage
 
Inscription : février 2008
Messages : 18
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 18
Points : 1
Points : 1
C'est possible de rechercher une chaine avec des expressions régulières qui contient un mot, n'en contient pas un autre, et en contient un 3e ?

Je veux récupérer une chaine qui contient <strong> ... <strong>
mais entre les 2 je veux être sûr qu'il n'y ait pas de </strong>
johann51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/03/2008, 13h27   #3
Membre chevronné
 
Avatar de Herode
 
Développeur Web
Inscription : mars 2005
Messages : 773
Détails du profil
Informations personnelles :
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : mars 2005
Messages : 773
Points : 795
Points : 795
Ca dépend des spécifications exactes du problème.
Dans le cas (simple) que tu cites, c'est possible en utilisant les références arrière :

Code :
1
2
$str = "<strong><strong>mot1</strong>mot2</strong>";
$out = preg_replace("{(<[^>]+>)(.*)(\\1)(.*)(<\/[^>]+>)(.*)(\\5)(.*)}", "$1$2$4$6$7$8", $str);
Mais s'il s'agit de traiter un document complexe comme une page HTML, ça risque d'être assez délicat.
En particulier, le motif ci-dessus n'intercepte que des balises sans attributs (la balise fermante a le même contenu que la balise ouvrant + un slash initial) et doit donc être affiné en fonction des besoins. En creusant un peu, on devrait facilement trouver d'autres soucis, par exemple, le motif ne traite pas bien :
Code :
$str = "<strong><strong>mot1</strong>mot2<strong>aaaaa</strong></strong>";
A mon avis, si tu veux nettoyer ton code HTML, mieux vaut procéder autrement que par les seules regex...
Herode est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/03/2008, 15h27   #4
Invité de passage
 
Inscription : février 2008
Messages : 18
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 18
Points : 1
Points : 1
Merci pour la réponse.

Effectivement, ça fonctionne pour le cas simple (avec un seul type de balise), mais dans une boucle.

Code :
1
2
3
4
5
6
 
while(preg_match('#<[^\/>]+>(.[^<\/>]*)?<[^\/>]+>#',$texte))
{
	$texte = preg_replace("{(<[^>]+>)(.*)(\\1)(.*)(<\/[^>]+>)(.*)(\\5)(.*)}", "$1$2$4$6$7$8", $texte);
}
echo $texte;
-----------------------------------------------------------------

J'ai étudié le code proposé, j'ai compris ce qui a été fait sauf :

que signifient ces parenthèses ?
johann51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/03/2008, 16h14   #5
Membre chevronné
 
Avatar de Herode
 
Développeur Web
Inscription : mars 2005
Messages : 773
Détails du profil
Informations personnelles :
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : mars 2005
Messages : 773
Points : 795
Points : 795
Oui, la recherche (.*) finale du motif empêche qu'il soit traité plusieurs fois. Pour éviter la boucle (et la gourmandise de l'opérateur *), une variante "améliorée" pour les cas toujours assez simples serait du genre :
Code :
1
2
3
$str = "<strong><strong>mot1</strong>mot2</strong>blabla<b><b>ddddd</b>aaa</b>";
$out = preg_replace("/(<[^>]+>)(.*?)(\\1)(.*?)(<\/[^>]+>)(.*?)(\\5)/", "$1$2$4$6$7$8", $str);
echo str_replace(array("<", ">"), array("[", "]"), print_r($out, true));
Les (\\1) et (\\5) sont les références arrière dont je parlais plus haut :
\1 récupère le texte satisfaisant la première parenthèse capturante (anti-slash doublé puisque c'est un caractère de contrôle : il faut de dé-spécialiser) : il récupère donc la première occurrence du mot capturé par la première paire de parenthèses.
Idem pour \5 en transposant.

Note que ça ne marche toujours que dans les cas simples de chaînes évoqués plus haut : une chaîne correcte comme
Code :
<strong>mot1</strong>aaaaaaaaaa<strong>mot2</strong>
ne sera pas correctement traitée, elle. Il faut retravailler l'expression régulière pour garantir qu'il n'y a pas de balise fermante du type capturé entre deux balises ouvrantes de ce même type. Et ce n'est que le début des ennuis à prévoir, sauf bien sûr si le code HTML à nettoyer est limité, d'un format stable, simple et bien cerné.
Herode est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/03/2008, 16h42   #6
Invité de passage
 
Inscription : février 2008
Messages : 18
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 18
Points : 1
Points : 1
Elle ne sera pas bien traitée car elle n'a pas besoin d'être traitée, non ?

Sinon, j'ai une autre question :

Si j'ai :

Code :
1
2
 
$texte = "<strong>11aa22zz33ee44tt</strong>";
Et que je veux récupérer que les chiffres, j'ai essayé ça :

Code :
1
2
 
$texte = preg_replace("#<strong>(([0-9]*)([^0-9]*))*</strong>#", "<strong>$2</strong>", $texte);

C'est possible de faire ça, de récupérer tous les chiffres entre 2 balises ? => 11223344 sachant que le groupe de lettres et de chiffres peut être variable
johann51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h15.


 
 
 
 
Partenaires

Hébergement Web