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 :

Je recherche une chaîne qui ne contient pas une certaine chaîne


Sujet :

Langage PHP

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 5
    Points
    5
    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.

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 5
    Points
    5
    Par défaut
    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>

  3. #3
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    $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...

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 5
    Points
    5
    Par défaut
    Merci pour la réponse.

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

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 ?

  5. #5
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    <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é.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 5
    Points
    5
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $texte = "<strong>11aa22zz33ee44tt</strong>";
    Et que je veux récupérer que les chiffres, j'ai essayé ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

Discussions similaires

  1. [RegEx] Expression qui ne contient pas une chaine
    Par coupolites dans le forum Langage
    Réponses: 5
    Dernier message: 02/03/2010, 10h07
  2. REGEX qui ne contient pas une sous-chaine
    Par Franky731 dans le forum C#
    Réponses: 4
    Dernier message: 02/04/2009, 15h11
  3. Réponses: 0
    Dernier message: 16/02/2009, 23h19
  4. Réponses: 3
    Dernier message: 20/02/2007, 15h48
  5. un module qui ne contient pas une fonction qu'il contient :?
    Par duplo dans le forum Général Python
    Réponses: 12
    Dernier message: 15/08/2006, 19h30

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