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 :

un preg_replace bizarre [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut un preg_replace bizarre
    Bonjour,

    Impossible de comprendre le comportement de ce preg_replace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    echo preg_replace(  Array(
                                    "/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])Text(?=\s|[[:punct:]])(?![^<>]*?>)(?=.*<\/a>)/",
                                    "/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])Text(?=\s|[[:punct:]])(?![^<>]*?>)(?!.*<\/a>)/",
                                    "/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])text(?=\s|[[:punct:]])(?![^<>]*?>)(?=.*<\/a>)/",
                                    "/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])text(?=\s|[[:punct:]])(?![^<>]*?>)(?!.*<\/a>)/"
     
                                ),
                                    Array(
                                    "<dfn>Text</dfn>",
                                    "<a href=\"index.php\"><dfn>Text</dfn></a>",
                                    "<dfn>text</dfn>",
                                    "<a href=\"index.php\"><dfn>text</dfn></a>"
                                ),
                                '<p>Text<br />text<br />Text<br />text<br />text</p>'
                                );
    Cela me remplace bien tous les "Text" et presque tous les "text" SAUF UN.
    Quand je dis SAUF UN, je parle de la première occurence "text" qui a été remplacé une fois (car il y a bien la balise <dfn> autour) mais le deuxieme remplacement ne s'est pas fait.

    Auriez vous une idée?

    Merci
    Quelqu'un aurait une idée du pourquoi ?

  2. #2
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    je suis toujours la dessus et je bloque vraiment pour l'instant. Je sais pas si je comprend mal le fonctionnement ou pas mais normalement, en faisant ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    echo preg_replace(  
    	Array(
    		"/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])Text(?=\s|[[:punct:]])(?![^<>]*?>)(?!.*<\/a>)/",
    		"/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])text(?=\s|[[:punct:]])(?![^<>]*?>)(?!.*<\/a>)/"
     
    	),
    	Array(
    		"<a href=\"index.php\"><dfn>Text</dfn></a>",
    		"<a href=\"index.php\"><dfn>text</dfn></a>"
    	),
    	'<p><dfn>text</dfn><br /><dfn>Text</dfn></p>'
    	);
    ça devrait bien trouver <dfn>Text</dfn> avec le T majuscule et me le remplacer par le premier élément de mon tableau de remplacement (<a href=\"index.php\"><dfn>Text</dfn></a>) puis ça devrait trouver <dfn>text</dfn> avec le t minuscule et le remplacer par le second élément de mon tableau de remplacement non ?

    Est ce qu'une bonne ame pourrait m'aider à cette comprehension ?

    merci

  3. #3
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 284
    Par défaut
    Je ne saurais pas t'expliquer ton cas. Néanmoins, si tu vires les tableaux pour les remplacer par une capture et un remplacement avec $1, ça donne le bon résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    echo preg_replace(  
    		"/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])([Tt])ext(?=\s|[[:punct:]])(?![^<>]*?>)(?!.*<\/a>)/",
    		"<a href=\"index.php\"><dfn>$1ext</dfn></a>",
    	'<p><dfn>text</dfn><br /><dfn>Text</dfn></p>'
    	);

  4. #4
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    Merci pour ta réponse Antoun.

    Le problème est que cette expression régulière est utilisé pour un module de glossaire qui me remplace tous les mots possédant une définition. Cela récupère le <body> de mon site et effectue les remplacements.

    Du coup, le tableau est indispensable pour lister toutes les définitions que j'ai.

    J'aimerai bien modifier l'expression régulière mais je ne suis pas sur de la comprendre entièrement et j'ai peur de la modifier pour la faire fonctionner et d'avoir de mauvaises surprises plus tard en voyant que je n'ai pas pris en compte certains cas.

    Dans le fonctionnement de celle-ci, je ne voit pas l'intérêt de mettre deux lignes pour un mot c'est a dire au lieu de remplacer le mot en le mettant entre balises <dfn> puis faire un second remplacement pour faire le lien, pourquoi ne pas tout faire d'un coup ?

    Pense tu qu'il est possible de le faire en une seule ligne pour chaque définition dans le tableau ?

    A mon sens (et d'après ce que comprend de cette expression), le seul cas où il ne faudrait pas remplacer le terme est le cas où celui-ci est déja entouré d'un lien à la base.

    Qu'en pense tu ?

    merci à toi.

  5. #5
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 284
    Par défaut
    Citation Envoyé par pop_up Voir le message
    Merci pour ta réponse Antoun.

    Le problème est que cette expression régulière est utilisé pour un module de glossaire qui me remplace tous les mots possédant une définition. Cela récupère le <body> de mon site et effectue les remplacements.

    Du coup, le tableau est indispensable pour lister toutes les définitions que j'ai.
    Non, tu pourrais faire une expression géante avec une alternative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (Abaque|Abbaye|Abbé...)
    Citation Envoyé par pop_up Voir le message

    J'aimerai bien modifier l'expression régulière mais je ne suis pas sur de la comprendre entièrement et j'ai peur de la modifier pour la faire fonctionner et d'avoir de mauvaises surprises plus tard en voyant que je n'ai pas pris en compte certains cas.

    Dans le fonctionnement de celle-ci, je ne voit pas l'intérêt de mettre deux lignes pour un mot c'est a dire au lieu de remplacer le mot en le mettant entre balises <dfn> puis faire un second remplacement pour faire le lien, pourquoi ne pas tout faire d'un coup ?
    C'est ça le fonctionnement ?
    Citation Envoyé par pop_up Voir le message
    Pense tu qu'il est possible de le faire en une seule ligne pour chaque définition dans le tableau ?
    A priori, oui, mais je suis très loin de comprendre ton système (ou du moins le système dont tu es l'heureux héritier )
    Citation Envoyé par pop_up Voir le message
    A mon sens (et d'après ce que comprend de cette expression), le seul cas où il ne faudrait pas remplacer le terme est le cas où celui-ci est déja entouré d'un lien à la base.

    Qu'en pense tu ?
    Ça semble logique. Mais effectivement, c'est assez difficile sans savoir précisément ni comment le système marche, ni comment il devrait marcher

  6. #6
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    Non, tu pourrais faire une expression géante avec une alternative :
    Sauf que j'ai pas tout mis car en fait le remplacement était plus compliqué. exemple pour une chaine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    echo preg_replace(  
    	Array(
    		"/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])text(?=\s|[[:punct:]])(?![^<>]*?>)(?=.*<\/a>)/",
    		"/(?!<a.*?)(?!<.*?)(?<=\s|[[:punct:]])text(?=\s|[[:punct:]])(?![^<>]*?>)(?!.*<\/a>)/"
    	),
    	Array(
    		"<dfn>Text</dfn>",
    		"<a href="index.php?id=372&amp;tx_a21glossary[uid]=23&amp;tx_a21glossary[back]=190&amp;cHash=6b2601bbb6" target="FEopenLink" onclick="vHWin=window.open('index.php?id=372&amp;tx_a21glossary[uid]=23&amp;tx_a21glossary[back]=190&amp;cHash=6b2601bbb6','FEopenLink','width=400,height=400');vHWin.focus();return false;" class="glossary"><dfn>text</dfn></a>"
    	),
    	'<p><dfn>text</dfn><br /><dfn>Text</dfn></p>'
    	);
    En réflechissant à comment le refaire, je pense que les cas où il ne faut pas remplacer sont :
    • Si celui-ci est déja dans un lien
    • Si celui-ci est dans une balise (genre title="" ou alt="")


    Pour l'instant j'en suis à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    echo preg_replace(  
    	Array
    (
        "/<a(.*)(Text|text)</a>/U",
        "/<a(.*)(Texto|texto)</a>/U",
        "/(!<a(.*)(Textes|textes)</a>/U"
    ),
    	Array
    (
        '<a href="index1.php">$1</dfn></a>',
        '<a href="index3.php"><dfn>$1</dfn></a>',
        '<a href="index2.php"><dfn>$1</dfn></a>'
    )
    ,
    	'<!--  Text: [begin] -->
    			 <br />Textes<br />texto<br /><a href="">textes</a><br />Text<br />
    		'
    	);
    Cette expression remplace à condition que le texte soit dans un lien. Maintenant j'aimerai savoir comment faire l'inverse à savoir, remplacer si celui-ci n'est pas dans un lien puis si celui-ci n'est pas dans une balise (un attribut de balise)

    Merci pour ton aide

  7. #7
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    J'ai avancé un peu et voila où j'en suis:

    Ceci ne fonctionne pas correctement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    echo preg_replace(  
    	Array
        (
        "#(?!<a.*?)(?!<.*?)(Pluies efficaces|pluies efficaces)(?![^<>]*?>)(?!.*<\/a>)#U",
        "#(?!<a.*?)(?!<.*?)(Nappes alluviales|nappes alluviales)(?![^<>]*?>)(?!.*<\/a>)#U",
        "#(?!<a.*?)(?!<.*?)(Nappes karstiques|nappes karstiques)(?![^<>]*?>)(?!.*<\/a>)#U"
        ),
        Array
        (
        '<a href="index1.php" style="color: red;">$1</dfn></a>',
        '<a href="index3.php" style="color: red;"><dfn>$1</dfn></a>',
        '<a href="index2.php" style="color: red;"><dfn>$1</dfn></a>'
        )
        ,
        '<ul><li> <a href="index.php?id=200" target="_top" >Visualiser les différentes nappes d\'eau souterraines</a></li><li>Les nappes alluviales</li><li>Les nappes karstiques</li><li>Un renouvellement lent</li><li>Le rôle des pluies efficaces</li></ul>
        '
    	);
    Alors que si je copie la même chose en mettant des retours à la ligne, ça fonctionne . exemple du même code qui fonctionne justa avec quelques sauts de ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    echo preg_replace(  
    	Array
        (
        "#(?!<a.*?)(?!<.*?)(Pluies efficaces|pluies efficaces)(?![^<>]*?>)(?!.*<\/a>)#U",
        "#(?!<a.*?)(?!<.*?)(Nappes alluviales|nappes alluviales)(?![^<>]*?>)(?!.*<\/a>)#U",
        "#(?!<a.*?)(?!<.*?)(Nappes karstiques|nappes karstiques)(?![^<>]*?>)(?!.*<\/a>)#U"
        ),
        Array
        (
        '<a href="index1.php" style="color: red;">$1</dfn></a>',
        '<a href="index3.php" style="color: red;"><dfn>$1</dfn></a>',
        '<a href="index2.php" style="color: red;"><dfn>$1</dfn></a>'
        )
        ,
        '<ul>
        <li> <a href="index.php?id=200" target="_top" >Visualiser les différentes nappes d\'eau souterraines</a></li>
        <li>Les nappes alluviales</li>
        <li>Les nappes karstiques</li>
        <li>Un renouvellement lent</li>
        <li>Le rôle des pluies efficaces</li>
        </ul>
        '
    	);
    Une idée sur ce qu'il faut que je rajoute pour que les sauts de lignes ne me posent pas problème dans le premier cas ?

    merci

  8. #8
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 284
    Par défaut
    Dans ce cas, à la fin de chaque regex, il faut ajouter le modificateur s (sauf si j'ai compris à l'envers, auquel cas c'est m). Donc #regex#U devient #regex#Us.

  9. #9
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    C'est justement ce que j'ai essayé mais en mettant , en plus du U, le s ou le m dans l'exemple du dessus (avec ou sans les retours à la ligne) ça ne marche pas correctement.

    C'est pour ça que je ne voit pas ce qu'il match pour ne pas les remplacer correctement.

  10. #10
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 284
    Par défaut
    J'ai essayé de comprendre ce que font tes regex... soit je rate un truc, soit le gars qui les a pondu n'a rien compris au mécanisme des assertions. Par exemple, (?![^<>]*?>) peut se traduire par "n'est pas suivi d'une non-balise", ce qui serait quand même plus simple en "est suivi par une balise", autrement dit, (?=[<>]). De même, les assertions de début n'ont pas vraiment de sens...

  11. #11
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    Juste une petite réponse pour dire ce que j'ai fait.
    Dans mon code Html, avant de faire mon preg_replace, j'ai fait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $body = str_replace(">",">\r\n",$body);
    C'est peut être bourrin mais ça al le mérite de faire fonctionner le truc.

    Ensuite il suffit de faire l'inverse car en html, le saut de ligne est considéré comme un espace pour certains éléments
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $body = str_replace(">\r\n",">",$body);

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RegEx] Résultat bizarre de mon preg_replace : doublement des e
    Par thecanea dans le forum Langage
    Réponses: 9
    Dernier message: 24/09/2009, 17h46
  2. problèmes bizarres avec jdbc
    Par jaimepasteevy dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 12/12/2003, 12h00
  3. taille de structure bizarre ...
    Par lyrau dans le forum C
    Réponses: 3
    Dernier message: 20/11/2003, 10h46
  4. Un String Bizarre
    Par YanK dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 11h05
  5. Réponses: 4
    Dernier message: 28/09/2002, 00h00

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