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 :

preg_replace: plantage étrange avec l'option 's' sur longue chaine [RegEx]


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 18
    Par défaut preg_replace: plantage étrange avec l'option 's' sur longue chaine
    Bonsoir,

    PHP Version 5.2.14

    je viens de passer la soirée sur un bug étrange. J'ai tenté d'isoler le problème dans le code épuré suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <?php
    $texte = '[lien NumLien=1]sfds[/lien]
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll';
     
    echo preg_replace('#\[lien (.*)NumLien=([0-9]+)(.*)(?: AfficheClics=([01]))?(.*)\](.*)\[/lien\]#s', 'bonjour',$texte);
    ?>
    EDITION: j'ai remplacé le replace_callback par un replace car, après vérification, ils se trouve qu'elles se comportent exactement de la même façon (mais replace a l'avantage de ne pas attirer l'attention sur une fonction anonyme dans la résolution du problème).

    Si tout fonctionne on devrait voir apparaître la chaîne inintelligible sur la page. Or la page est blanche, ce qui indique que preg_replace_callback a planté, ne renvoyant pas de texte.

    MAIS j'ai trouvé 4 cas dans lesquels ça fonctionne à nouveau:

    - on enlève l'option s.

    - on réduit le nombre de caractères en supprimant une des lignes de la chaîne.

    - on enlève la première ligne, elle qui colle à l'expression régulière (y compris si on la remplace par un nombre équivalant ou supérieur de caractères.

    - on enlève de l'expression régulière par exemple le paramètre '(.*)' du milieu, qui se trouve juste avant '(?: AfficheClics...', ou bien son petit frère juste avant le crochet fermant échappé.

    Qu'en pensez-vous?

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bonjour,


    Je ne comprends pas ce qu’est censé faire ton code.

    Qu’est ce que tu appelles la chaîne inintelligible ?
    ’sfds’ ?
    Car ta RE, se terminant par [/lien\] , le résultat ne peut dépendre en rien de ce qui se trouve au delà de '[/lien]' dans la chaîne $texte.

    Je pense d’autre part qu’il faut un ’return quelque chose’ dans le code de create_function et non pas simplement ''

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 18
    Par défaut
    Bien sûr le code original contient des instructions dans le create_function mais que celles-ci soient présentes ou non ne changeait rien au bug, c'est pourquoi je les ai enlevées (si du texte correspond à l'expression régulière il est dès lors remplacé par... rien, il est tout simplement supprimé). Bien sûr également le résultat ne peut dépendre ce qui se trouve au delà de [/lien] et c'est bien ça qui est étrange. D'autant plus que le problème n'est pas que le résultat est faux, mais qu'il n'y a pas de résultat, aucun texte, n'est renvoyé par preg_replace_callback.
    Ce que j'appelle chaîne inintelligible est l'ensemble de la chaîne $texte, remplie de caractères au hasard à part pour la première ligne.

    Ce code est réduit au minimum utile à la démonstration qu'il plante avec ma version de PHP, et qu'il ne plante plus au moins quand on lui applique une de mes 4 modifications présentées dans mon précédent message. À savoir: on enlève l'option s, on en lève une ligne de la chaine,...

    Est-ce que quelqu'un ayant la même versiond de php (ou même une autre) reproduit le même plantage?


    EDITION: j'ai remplacé le replace_callback par un replace car, après vérification, ils se trouve qu'elles se comportent exactement de la même façon (mais replace a l'avantage de ne pas attirer l'attention sur une fonction anonyme dans la résolution du problème).

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 18
    Par défaut
    Citation Envoyé par Florimond Voir le message
    EDITION: j'ai remplacé le replace_callback par un replace car, après vérification, ils se trouve qu'elles se comportent exactement de la même façon (mais replace a l'avantage de ne pas attirer l'attention sur une fonction anonyme dans la résolution du problème).
    Donc, Raphael, as-tu fais le test comme moi sans rien dans la fonction, et puis avec ton return "LIEN", pour démontrer que c'est bien ça qui ne fonctionne pas?

    De plus je crois avoir montré que c'était précisément ma regex, telle quelle qui faisait planter la fonction (replace ou replacecallback), donc ton test est doublement inutile. Peux-tu recommencer avec ma regex ET la même quantité de texte ET un texte comprenant un morceau qui match à l'expression régulière. Puis si ça ne fonctionne pas, enlever le texte qui match, ou une ligne du texte au hasard, ou l'option 's' etc..

    Enfin possède-tu la même version de php que moi?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 18
    Par défaut
    Avec php version 5.3.2-1, même problème.

    Par contre le code Perl équivalant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $texte = '[lien NumLien=1]sfds[/lien]
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll';
     
    $texte =~ s#\[lien (.*)NumLien=([0-9]+)(.*)(?: AfficheClics=([01]))?(.*)\](.*)\[/lien\]#bonjour#s;
     
    print $texte;
    fonctionne parfaitement comme attendu, y compris si mon

    [lien(...)]blabla
    blabla[/lien]

    est étalé sur plusieurs lignes. Perl V5.10.1

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    1)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $texte = '[lien NumLien=1]sfds[/lien]
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll';
    À quoi cela peut-il bien servir de faire suivre 40 ’ù’ puis 21fois ’k’ puis 51 fois ’l’
    Qu’est ce que ça apporte ?



    2)

    Ce que j'appelle chaîne inintelligible est l'ensemble de la chaîne $texte, remplie de caractères au hasard à part pour la première ligne.
    Ce n’est pas clair à cause de l’ambigüité de ce à quoi se rapporte « à part pour la première ligne »

    La phrase signifie-t-elle:

    - que la première ligne n’est pas remplie de caractères au hasard ?

    - ou que la première ligne est exclue de ce que tu appelles “chaîne inintelligible“ ?

    Pourrais tu répondre, s’il te plait, en donnant explicitement la chaîne contenue dans $texte, que tu considères comme inintelligible ? Merci.

    L’aide que l’on peut t’apporter passe obligatoirement par la compréhension de ce que tu appelles “chaîne inintelligible“ puisque son apparition en tant que résultat constitue la définition de la réussite du programme voulu:

    Citation Envoyé par Florimond Voir le message
    Si tout fonctionne on devrait voir apparaître la chaîne inintelligible sur la page.



    3)

    eyquem
    Je pense d’autre part qu’il faut un ’return quelque chose’ dans le code de create_function et non pas simplement ''
    Florimond
    Bien sûr le code original contient des instructions dans le create_function mais que celles-ci soient présentes ou non ne changeait rien au bug, c'est pourquoi je les ai enlevées (si du texte correspond à l'expression régulière il est dès lors remplacé par... rien, il est tout simplement supprimé).
    Il serait mieux de nous dire quelles sortes d’instructions étaient présentes avant que tu trouves inutile de les garder. Cela nous permettrait de savoir si ces instructions que tu as décidé d’enlever comportaient un return ou non.

    Car ta réponse n’en est pas une sur ce point précis, alors que c’est celui qui m’a paru le plus immédiatement en cause.
    Ce que tu apportes par rapport à ton premier post, et l’appui de Rapha222, me poussent à considérer qu’il ne faut pas laisser tomber si rapidement cette piste.

    En effet, d'apres
    Citation Envoyé par Florimond #3 Voir le message
    (si du texte correspond à l'expression régulière....
    on peut légitimement en déduire que tu as vérifié que l’expression régulière capte bien quelque chose.
    Est-ce bien ce que tu voulais ? Il faut le préciser.

    Mais
    a-
    Citation Envoyé par Florimond #3 Voir le message
    (si du texte correspond à l'expression régulière il est dès lors remplacé par... rien, il est tout simplement supprimé)
    l'expression réguliere n'étant pas en cause, c’est bien que c'est preg_replace_callback qui foire, non ?

    D'ailleurs , tu l'as écrit toi meme des le début:
    b-
    Citation Envoyé par Florimond #1 Voir le message
    Or la page est blanche, ce qui indique que preg_replace_callback a planté, ne renvoyant pas de texte.
    On ne comprend soit dit en passant plus rien quand on lit ensuite:
    Citation Envoyé par Florimond #5 Voir le message
    De plus je crois avoir montré que c'était précisément ma regex, telle quelle qui faisait planter la fonction (replace ou replacecallback),

    -------------------------------

    Or pour moi y a pas 36 possibilités pour que preg_replace_callback() foire. Vue la simplicité de ses arguments, c'est que c'est create_function() qui la fait foirer.



    Donc , en continuant sur mon idée, j'ai trouvé:

    string create_function ( string $args , string $code )

    Valeurs de retour

    Retourne un nom de fonction unique, sous la forme d'une chaîne de caractères, ou FALSE si une erreur survient.

    http://www.php.net/manual/fr/functio...e-function.php

    mixed preg_replace_callback ( mixed $pattern , callback $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )

    Valeurs de retour

    preg_replace_callback() retourne un tableau si le paramètre subject est un tableau, ou, sinon, une chaîne de caractères. Si une erreur survient, la valeur retournée sera NULL.

    http://www.php.net/manual/fr/functio...e-callback.php
    Pour moi, l’absence de return dans la create_function() du premier post original fait qu’elle renvoie False, ce qui est cause que preg_replace_callback() renvoit Null.
    La page blanche qui s’affiche, c’est donc Null.



    4)

    Ce n’est pas une bonne chose de faire un EDIT dans le premier post, en changeant autant de choses que
    preg_replace_callback() par preg_replace()
    et
    '' par ’bonjour’.

    Il aurait fallu commencer par nous dire si de spécifier ’bonjour’ à la place de '' donnait un résultat différent avec le premier code comportant preg_replace_callback().

    Mais maintenant cela est devenu d’une grande confusion, on se perd dans ce à quoi se rapportent les réponses antérieures au changement et à quelles conditions d’exécution se rapportent les résultats.





    5)

    Par contre le code Perl équivalent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $texte = '[lien NumLien=1]sfds[/lien]
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll
    camùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùklkkkkkkkkkkkkkkkkkkkkkjjhklllllllllllllllllllllllllllllllllllllllllllllllllll';
     
    $texte =~ s#\[lien (.*)NumLien=([0-9]+)(.*)(?: AfficheClics=([01]))?(.*)\](.*)\[/lien\]#bonjour#s;
     
    print $texte;
    fonctionne parfaitement comme attendu, y compris si mon
    [lien(...)]blabla
    blabla
    [/lien]
    est étalé sur plusieurs lignes.
    Sauf que dans l’exemple , ’camùùùùùùùùùùùùùùùùùùùùù.....’ n’est pas du blabla blalbla compris entre [lien] et [/lien] puisqu’il est après.

    C’est une pagaille ton truc.

  7. #7
    Membre confirmé Avatar de Rapha222
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 128
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Je pense d’autre part qu’il faut un ’return quelque chose’ dans le code de create_function et non pas simplement ''
    +1, tu t'es trompé dans l'utilisation du Callback :

    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
    25
    26
     
    [rapha@desktop Bureau]$ cat test.php
    <?php                                                                                                               
    $texte = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.                                                  
    Maecenas lectus felis, rhoncus a pretium ut, iaculis at mi.                                                         
    Curabitur mollis pellentesque purus, eget tristique dolor cursus at.                                                
    Nulla mattis consequat eros a cond [lien]sfds[/lien] lorem ipsum.                                                   
    Fusce quis tortor leo, eget consequat purus.
    Nam et magna sed ante luctus porttitor vel ut lectus.
    Ut in dui ut nunc varius adipiscing.
    ';
     
    echo preg_replace_callback('#\[lien\](.*)\[/lien\]#',
                               create_function('$param',
                                    'return "LIEN";'),
                               $texte);
    ?>
     
    [rapha@desktop Bureau]$ php test.php
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Maecenas lectus felis, rhoncus a pretium ut, iaculis at mi.
    Curabitur mollis pellentesque purus, eget tristique dolor cursus at.
    Nulla mattis consequat eros a cond LIEN lorem ipsum.
    Fusce quis tortor leo, eget consequat purus.
    Nam et magna sed ante luctus porttitor vel ut lectus.
    Ut in dui ut nunc varius adipiscing.

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

Discussions similaires

  1. Soucis avec l'option "Bridged" sur VMWARE
    Par Jovan dans le forum VMware
    Réponses: 1
    Dernier message: 10/02/2015, 15h50
  2. Recherche RPG avec option coopération sur PS3
    Par clairetj dans le forum Consoles
    Réponses: 13
    Dernier message: 08/07/2014, 08h35
  3. Réponses: 14
    Dernier message: 21/09/2012, 14h05
  4. [WD10] plantage appli avec vista sur impression Etat
    Par mnssylvain dans le forum WinDev
    Réponses: 3
    Dernier message: 27/11/2008, 19h02
  5. Réponses: 3
    Dernier message: 04/11/2007, 19h55

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