preg_remplace

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : preg_remplace

par traker » 05 juin 2008, 14:31

ok je conprend un peut mieux
encore une question

dans tout les cas le contenu du masque rentre dans le tableau comme si il y avait des () c'est comme si le masque etait #(value="(.*)")#

je penssai que seul le contenu de () rentre dans le array

ok merci beaucoup

par FredoMkb » 04 juin 2008, 15:43

Re... :)

Bon bon, je ne suis pas spécialiste des regex, mais je vais essayer de décortiquer un peu la chose...

Partons donc du principe que nous avons un texte Html de ce type (ce bidon hein ;) , c'est juste en guise d'exemple) :
$html = '<p>Inter quae [email protected] verbum emicuit 
si value="fortes" decorum, et si versus paulo concinnior unus et alter, 
iniuste totum ducit venditque poema.</p>
<select>
<option value="y01234">yyyyyyy</option>
<option value="9874xX">xxxxxxx</option>
<option value="zZ33Zz">zzzzzzz</option>
</select>
<div>Non equidem insector une <Option carmina Livi esse, memini quae plagosum 
mihi Value="UnoDos" parvo Orbilium dictare; sed emendata videri pulchraque 
et exactis /oPtiOn> distantia miror.</div>';
Maintenant, admettons qu'on souhaite récupérer uniquement le contenu de l'attribut "value", ok ?

Une première solution serait d'imaginer le masque suivant :
$masque = '#value="(.*)"#';
Ce qui nous donnerait comme résultat, dans la variable "$liste", avec la fonction "preg_match_all" :
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
            [0] => value="fortes"
            [1] => value="y01234"
            [2] => value="9874xX"
            [3] => value="zZ33Zz"
        )

    [1] => Array
        (
            [0] => fortes
            [1] => y01234
            [2] => 9874xX
            [3] => zZ33Zz
        )

)
*/
Ok, jusqu'à là ça ne devrait pas poser de problème, tout fonctionne, nous récupérons un tableau multidimensionnel avec une première liste d'éléments correspondants au masque entier recherché, puis une seconde liste avec seulement les données retournées par les parenthèses capturantes...

Tout est ok... sauf que, is on regarde de plus près, on se s'aperçois qu'on récupère également un attribut "value" qui ne vient pas des balises "option", la toute première : "[0] => fortes"...

Or, c'est uniquement les valeurs des balises "option" que nous souhaitons récupérer, nous devons donc affiner notre masque, en lui donnant comme indication qu'il doit uniquement chercher à l'intérieur des balises "<option" et "option>"... le masque devient quelque chose comme :
$masque = '#<option.*value="(.*)".*option>#';
Et le résultat devrait être :
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
            [0] => yyyyyyy
            [1] => xxxxxxx
            [2] => zzzzzzz
        )

    [1] => Array
        (
            [0] => y01234
            [1] => 9874xX
            [2] => zZ33Zz
        )

)
*/
Bon, là on a éliminé la valeur qui nous gênait, c'est-à-dire, celle qui n'était pas issue d'une balise "option"...

Mais, c'est bizarre, nous avons apparemment un comportement étrange, en effet, au lieu d'avoir, dans la première liste d'éléments, l'ensemble du texte retourné par le masque, on a seulement les valeurs figurant dans les balises "option"... :shock:

Bon, ce n'est qu'une apparence, car en réalité, si on regarde le code source de la page, on constate que les balises "option" ont été entièrement récupérées par le masque... ce qui nous donne donc :
/*
Array
(
    [0] => Array
        (
            [0] => <option value="y01234">yyyyyyy</option>
            [1] => <option value="9874xX">xxxxxxx</option>
            [2] => <option value="zZ33Zz">zzzzzzz</option>
        )

    [1] => Array
        (
            [0] => y01234
            [1] => 9874xX
            [2] => zZ33Zz
        )

)
*/
Ok, c'est bon, là on a exactement ce qu'on voulait... on pourrait s'arrêter là, mais il y a peut-être moyen d'optimiser le masque afin qu'il soit plus rapide et efficace.

Comme nous savons exactement ce que l'attribut "value" contient ou, du moins, quelle est sa structure de données, on peut décider de modifier notre parenthèse capturante pour remplacer notre recherche générique "(.*)" par une plus spécifique, telle que tu l'as imaginé par exemple "([A-Z09]{6})", on test :
$masque = '#<option.*value="([A-Z0-9]{06})".*option>#';
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
        )

    [1] => Array
        (
        )

)
*/
Et là, damned :evil: plus rien du tout :(

Et oui, nous devons indiquer au masque que la recherche doit se faire insensible à la casse (insensible aux majuscules et minuscules), on ajoute donc l'option "i" qui est justement prévue à cet effet... on re-test :
$masque = '#<option.*value="([A-Z0-9]{06})".*option>#i';
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
            [0] => <option value="y01234">yyyyyyy</option>
            [1] => <option value="9874xX">xxxxxxx</option>
            [2] => <option value="zZ33Zz">zzzzzzz</option>
            [3] => <Option carmina Livi esse, memini quae plagosum mihi 
Value="UnoDos" parvo Orbilium dictare; sed emendata videri pulchraque et exactis /oPtiOn>
        )

    [1] => Array
        (
            [0] => y01234
            [1] => 9874xX
            [2] => zZ33Zz
            [3] => UnoDos
        )

)
*/
Bon, on y était presque... mais on récupère encore un truc ignoble qui traînait en dernière ligne :( ... comment s'en débarrasser ? :shock:

Si on regarde en détail, on constate que les balises "option" présentes dans cette dernière ligne son écrites avec des majuscules et minuscules, il serait donc intéressant, pour éviter de récupérer ces cas de figure, de limiter la recherche aux minuscules uniquement... mais là on doit donc supprimer l'option "i" de notre masque, ce qui est plutôt embêtant puisque les valeurs qu'on cherche peuvent contenir des caractères de différente casse...

Le plus simple, est d'ajouter les minuscules à notre parenthèse capturante tout en éliminant l'option "i" :
$masque = '#<option.*value="([a-zA-Z0-9]{06})".*option>#';
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
            [0] => <option value="y01234">yyyyyyy</option>
            [1] => <option value="9874xX">xxxxxxx</option>
            [2] => <option value="zZ33Zz">zzzzzzz</option>
        )

    [1] => Array
        (
            [0] => y01234
            [1] => 9874xX
            [2] => zZ33Zz
        )

)
*/
Voilà... on a tout bon maintenant !!! \:D/

Juste une dernière petite modif et tout sera parfait (enfin, façon de dire ;) )...

Si jamais, pour une raison ou pour une autre, au lieu d'avoir les balises "option" chacune dans une ligne différente on en trouvait certaines dans la même ligne, alors notre masque produirait un résultat incomplet :
$html = '<p>Inter quae [email protected] verbum emicuit 
si value="fortes" decorum, et si versus paulo concinnior unus et alter, 
iniuste totum ducit venditque poema.</p>
<select>
<option value="y01234">yyyyyyy</option><option value="9874xX">xxxxxxx</option>
<option value="zZ33Zz">zzzzzzz</option>
</select>
<div>Non equidem insector une <Option carmina Livi esse, memini quae plagosum 
mihi Value="UnoDos" parvo Orbilium dictare; sed emendata videri pulchraque 
et exactis /oPtiOn> distantia miror.</div>';
$masque = '#<option.*value="([a-zA-Z0-9]{06})".*option>#';
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
            [0] => <option value="y01234">yyyyyyy</option><option value="9874xX">xxxxxxx</option>
            [1] => <option value="zZ33Zz">zzzzzzz</option>
        )

    [1] => Array
        (
            [0] => 9874xX
            [1] => zZ33Zz
        )

)
*/
Pour éviter ce soucis, il suffit d'utiliser l'option "U" qui oblige la fonction "preg_match_all" a ne pas étendre sa recherche dès que le masque a été trouvé :
$masque = '#<option.*value="([a-zA-Z0-9]{06})".*option>#U';
preg_match_all($masque, $html, $liste);
print_r($liste);
/*
Array
(
    [0] => Array
        (
            [0] => <option value="y01234">yyyyyyy</option>
            [1] => <option value="9874xX">xxxxxxx</option>
            [2] => <option value="zZ33Zz">zzzzzzz</option>
        )

    [1] => Array
        (
            [0] => y01234
            [1] => 9874xX
            [2] => zZ33Zz
        )

)
*/
Voilà... j'espère n'avoir rien oublié... enfin, il y a toujours des cas de figure auxquels on n'a pas pensé, mais bon... ce sera pour une prochaine... (...enfin, si on n'avait que ça à faire... ;) )

à+ :)

par traker » 04 juin 2008, 10:30

pas sur non plus :)

normalement dans l'exemple suivant
$masque = '#<option.*value="([A-Z0-9]{6})".*/option>#iU';

il y a que les caractere entre les parentese "capturante" qui doivent ce trouvé enregistre dans le array dans l'exemple c'est 7(1+6) caracteres lettre Maj. + chiffre (les Maj sont annule avec l'option i)

et moi le truc c'est qu'il me fait un array dans array avec le capturante
exp:
print_r($liste[0]); // Array ( [0] => yyyyyyy [1] => xxxxx [2] => zzzzzz )
print_r($liste);Array ( [0] => Array ( [0] => yyyyyy [1] => xxxxxx [2] => zzzzzz ) [1] => Array ( [0] => yyyyyy [1] => xxxxxx [2] => zzzzzz ) )

ca marche mais au cas ou pourquoi il me fait ca puisque je lui est dit de me trouver ([A-Z0-9]{6}) qui ce trouve entre les "" et non pas le .* qui viens apres surtout dans les cas il devrait metre aussi les >< dans ma chaine j'ai ....xxxx">xxxxxx</....

G du mal
merci encore pour tes reponces rapide en plus

par FredoMkb » 04 juin 2008, 09:30

Bonjour :)
c'est preg_match_all pour les sortir de la chaine !!?? et l'option U c'est pour quoi??
La fonction "preg_match_all" analyse tout le texte fourni et isole, dans une variable type tableau multidimensionnel, tous les textes qui correspondent au masque de recherche fourni...

En gros, ici on dit à la fonction "preg_match_all" de chercher tout ce qui commence par "<option" et fini par "option>", avec quelques subtilités à l'intérieur, notamment l'attribut "valeur=" et les parenthèses capturantes "(.*)" qui vont servir à récupérer la valeur de la balise...

Pour l'option "U", elle indique à la fonction "preg_match_all" de faire une recherche non gourmande, c'est à dire que dès qu'un masque est trouvé, on passe à la recherche suivante, ce qui évite qu'il englobe tout le texte situé entre le premier "<option" trouvé et le dernier "option>" existant dans le texte... (mmm... pas sûr d'être clair là :shock: )...

à+ :)

par traker » 04 juin 2008, 09:09

merci
ba c'est tout a fait ca apres je les sort du array
c'est preg_match_all pour les sortir de la chaine !!?? et l'option U c'est pour quoi??

MERCI encore

par FredoMkb » 03 juin 2008, 19:35

Bonjour :)

Voici ce que je viens d'essayer :
$html = '<option value="yyyyyy">yyyyyyy</option>
<option value="xxxxxx" >xxxxx</option>
<option value="zzzzzz" >zzzzzz</option>';

$masque = '#<option.*value="(.*)".*option>#U';
preg_match_all($masque, $html, $liste);

print_r($liste[0]); // Array ( [0] => yyyyyyy [1] => xxxxx [2] => zzzzzz )
Je ne sais pas si cela correspond à ce que tu voulais faire et donc si ça peut te rendre service... à tout hasard... ;)

à+ :)

preg_remplace

par traker » 03 juin 2008, 17:43

voila je tente d'extraire une chaine avec preg_remplace mais ca marche pas avec moi

j'ouvre un fichier contenant ce type de donnée
<option value="yyyyyy" >yyyyyyy</option
<option value="xxxxxx" >xxxxx</option
<option value="zzzzzz" >zzzzzz</option
etc...
chaque chaine de yyyyy par ligne est d'efférente mais elle font la mémé taille

je veux mettre yyyyyy dans une variable différente ou dans un tableau avec des entre différente
exp:
$y="yyyyyy"
$x="xxxxxx"ets..
$i[1]="yyyyyyy"
$i[2]="xxxxxxx"

j'ai test avec ereg avec preg_remplace et preg_match ca va pas ou il me supprime les yyyyyy ou il me les met dans une seul variable et je peut plus rien en faire

voila quelque ligne pour exemple
$contents = preg_replace('#<#', 'xx', $contents);//je sup les < pour afficher les ligne
$contents = preg_replace('#>#', 'yy', $contents);//je sup les > pour afficher les ligne
//$texte = preg_replace('#>([A-Z0-9]{7})<#', '$1', $contents);
//$texte = preg_replace('#([^A-Z0-9])#s', '', $contents);
//$texte = preg_replace('#([A-Z0-9]{7})#s', '$1 ', $texte);//le 7 car la chaine a extraire est de 7
//$texte = preg_split('#("[^A-Z0-9]{7}")#s',$contents);
//print_r($texte);
//echo "<br>".$texte;

$xy=array();
for($i=1;$i<100;$i++){
$xy['{.$i.}']=ereg ("([A-Z0-9]{7})", $contents, $regs);
$xy[$i]=$regs[1];
echo $xy[$i]."<br>".$i."<br>";

}

c'est un peut le b...... mais c'est des test

si vous pouvez me mettre sur un chemin
merci cordialement