bien parsé une chaine

Yohan
Invité n'ayant pas de compte PHPfrance

08 avr. 2008, 01:27

Bonjour,
Je suis en train de mettre en place un site permettant de traité des sms et de les mettre dans une base de données permettant de gérer un parc informatique de setup box.Pour ce faire je dois traité le sms reçu pour récupéré les différentes infos nécessaire.
Malheureusement toutes mes variables ne contiennent que des array après traitement.Je ne vois pas ou j'ai fauté pour le parsage.Le message est bien reçu puisque sur ma page j'affiche le message contenu dans content après plus rien.Un sms a cette forme :

smim gekobox69945282806/Apr/02:006/Apr/02:0Bonne04345c69e70280||1&& gekobox69945282806/Mar/02:006/Apr/02:0Bonne04345c69e70280||2&&gekobox69945282806/Apr/02:006/Apr/02:0Bonne04345c69e70280||3

Chaque box différentes est séparé par '&&' et 'II' sépare la sauvegarde du reste de l'info.
VOilà mon code:
<?p
//supression premier mot (smim) qui ne sert à rien
$content = urlencode(substr(strstr($content," "),1));
echo 'Content : '.$content.'<br />';
//séparation grâce aux délimiteurs des différents tags, du corps de chacun et de la sauvegarde
foreach ($lines as $lines) :
$lines = explode("&&", $content);
list($str, $sauv) = explode("||", $lines);

//séparation du corps sans délimiteurs avec les tailles des données grâce à strsplit
$nom = str_split($str,7);
$num = str_split($str,10);
$datei = str_split($str,11);
$dater = str_split($str,11);
$etat = str_split($str,5);
$uid = str_split($str,14);
?>
Pourquoi es ce que je parse mal cette chaîne?

Merci pour votre aide.

ViPHP
ViPHP | 4674 Messages

08 avr. 2008, 11:49

Hey,

il serait préférable d'utiliser les expressions régulières. Est-ce que tu connais ? Si non, un excellent site pour apprendre : lumadis.be, voir la partie tutoriel (excellente).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

08 avr. 2008, 11:50

La fonction explode() transforme une chaine en un tableau d'éléments. Quand tu fais : $lines = explode("&&", $content) de ta chaine, tu obtiens le tableau suivant:
$lines = array (
  0 => 'smim gekobox69945282806/Apr/02:006/Apr/02:0Bonne04345c69e70280||1'
  1 => 'gekobox69945282806/Mar/02:006/Apr/02:0Bonne04345c69e70280||2'
  2 => 'gekobox69945282806/Apr/02:006/Apr/02:0Bonne04345c69e70280||3'
);
Ce n'est donc pas $lines qu'il te faut ensuite "exploser" sur le ||, mais chacun des éléments de ce tableau :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Jayden
Invité n'ayant pas de compte PHPfrance

08 avr. 2008, 18:33

Grace à Sadeq j'ai pu corrigé mon code j'obtiens donc
<?p
//supression premier mot (smim) qui ne sert à rien
$content = trim(urlencode(str_replace("smim ", "" , $content)));
echo 'Content : '.$content.'<br />'; 

//séparation grâce aux délimiteurs des différents tags, du corps de chacun et de la sauvegarde

//Découpage de $content sous forme d'un tableau $lines
$lines = explode("&&", $content);
echo 'Lines : '.$lines.'<br />';
//boucle de parcours du tableau $lines ligne par ligne nommée $line
foreach ($lines as $line)
{
   //Récup des données $str et du n° de sauvegarde $sauv à partir d'une ligne $line
   list($str, $sauv) = explode("||", $line);

   //séparation du corps sans délimiteurs avec les tailles des données grâce à strsplit
  $nom = str_split($str,7);
  $num = str_split($str,10);
  $datei = str_split($str,11);
  $dater = str_split($str,11);
  $etat = str_split($str,5);
  $uid = str_split($str,14); 
  //Après on peut utiliser les données extraites pour les affichés pour voir si traitement correctement effectué
echo "nom : ";print_r ($nom);
echo "<br />";
echo "num: ";print_r ($num);
echo "<br />";
echo 'datei : ';print_r ($datei);
echo "<br />";
echo 'dater : ';print_r ($dater);
echo "<br />";
echo 'etat : ';print_r ($etat);
echo "<br />";
echo 'uid : ';print_r ($uid);

?>
Maintenant je n'ai plus de array par contre quand j'affiche le contenu directement sur ma page j'ai ce résultat là=

http://trefle2.org/sms/Gestion.php



J'utilise mal str_plit.Puisque chaque valeur de mon message se retrouve dans un tableau contenant un charactère et je n'arrive pas à voir mon erreur. :(

ViPHP
ViPHP | 4674 Messages

08 avr. 2008, 18:38

Je dois être bigleux hein, mais à quel moment est-ce que tu fermes ta boucle ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Jayden
Invité n'ayant pas de compte PHPfrance

08 avr. 2008, 18:52

Désolé je n'avais pas mis mon code jusqu'à la fin du foreach.Je l'ai ajouté.
Finalement à la la place de str_split jutilise substr et ca marche sauf que j'ai fait des petites erreurs pour le parsage.Voilà mon nouveau code:
<?p
foreach ($lines as $line)
{
   //Récup des données $str et du n° de sauvegarde $sauv à partir d'une ligne $line
   list($str, $sauv) = explode("||", $line);


   //séparation du corps sans délimiteurs avec les tailles des données grâce à strsplit
$nom=substr($str, 0, 7);
$num=substr($str, 7, 10);
$datei=substr($str, 17, 11);
$dater=substr($str, 28, 11);
$etat=substr($str, 39, 5);
$uid=substr($str, 44, 14);
  //$nom = str_split($str,7);
  //$num = str_split($str,10);
 // $datei = str_split($str,11);
 // $dater = str_split($str,11);
//  $etat = str_split($str,5);
//  $uid = str_split($str,14); 
  //Après on peut utiliser les données extraites pour les affichés pour voir si traitement correctement effectué
echo "nom : ";print_r ($nom);
echo "<br />";
echo "num: ";print_r ($num);
echo "<br />";
echo 'datei : ';print_r ($datei);
echo "<br />";
echo 'dater : ';print_r ($dater);
echo "<br />";
echo 'etat : ';print_r ($etat);
echo "<br />";
echo 'uid : ';print_r ($uid);

//Insertion dans la base de donnée.
$sql = mysql_query("INSERT INTO Opérateur SET Produit='$nom', Op='$num', DatI='$dati', DatR='$dater', Etat='$etat'");
} 
?>

Invité
Invité n'ayant pas de compte PHPfrance

09 avr. 2008, 09:52

Maintenant je découpe bien ma chaine mais seulement le début.Ca ne parse pas les données se trouvant après &&.POur par exemple ce sms:
smim Gekobox069945282806/Apr/200806/Apr/2008Bonne04345c69e70280||2&&Gekobox069945282806/Apr/200806/Apr/2008Mauva04345c69e70280||3

Je ne parse que cette partie:
Gekobox069945282806/Apr/200806/Apr/2008Bonne04345c69e70280||2
Voilà mon code:
<?p
{//cas de réception sms pour ajout à la base de donnée
//supression premier mot (smim) qui ne sert à rien
$content = trim(urlencode(str_replace("smim ", "" , $content)));
echo 'Content : '.$content.'<br />'; 

//séparation grâce aux délimiteurs des différents tags, du corps de chacun et de la sauvegarde

//Découpage de $content sous forme d'un tableau $lines
$lines = explode("&&", $content);

//boucle de parcours du tableau $lines ligne par ligne nommée $line
foreach ($lines as $line)
{
   //Récup des données $str et du n° de sauvegarde $sauv à partir d'une ligne $line
   list($str, $sauv) = explode("||", $line);


//séparation du corps sans délimiteurs avec les tailles des données grâce à substr 
$nom=substr($str, 0, 7);
$num=substr($str, 7, 10);
$datei=substr($str, 17, 15);
$dater=substr($str, 32, 15);
$etat=substr($str, 47, 5);
$uid=substr($str, 52, 14);

//Insertion dans la base de donnée.
$sql = mysql_query("INSERT INTO Opérateur SET Produit='$nom', Op='$num', DatI='$dati', DatR='$dater', Etat='$etat'");
} }?>
Quel erreur ai-je encore commise?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

09 avr. 2008, 10:55

A priori, je ne vois pas d'erreur au niveau de ton code... affiche les valeurs de $lines (avec un print_r() puisque c'est un tableau) et de $line (avec un echo)...
affiche un message dans la boucle foreach pour voir combien de fois il rentre dedans (et quelle est la valeur de $line pour chaque passage) ...
affiche la requête sql avant de l'exécuter (passe par une variable au lieu de donner la chaine directement à mysql_query()) ... vérifie que ta ou tes requêtes sont correctes et/ou test le résultat de leur exécution ...
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
ViPHP | 4674 Messages

09 avr. 2008, 12:10

Puisque tu es décidé à ne pas utiliser les expressions régulières, je te montre comment ton problème peut être résolue en 2 lignes. Le but, c'est de te faire apprendre :).

Première expression, on sépare le smim du reste, indépendamment du nombre d'espace entre les deux parties :

Code : Tout sélectionner

^smim\s*(.*)$
Seconde expression, on éclate partie par partie la chaîne avec un motif qui se répète autour des && (séparateur des grosses parties) :

Code : Tout sélectionner

(.{7})([0-9]{12})/([a-zA-Z]{3})/([0-9]{6})/([a-zA-Z]{3})/([0-9]{4})(.{5})(.{14})\|\|([^&&]+)
L'avantage avec ton motif, c'est qu'il est simple, dans le sens où il est fixé. Chaque longueur des parties à éclater a une taille fixe (7 pour la boîte, puis 12 pour le téléphone, puis 3 pour le mois, puis 6 ...). Il n'y a que la dernière partie (que tu appelles $sauv) dont on ne connaît pas la taille. Mais ce n'est pas un soucis, on sait qu'elle occupe tout l'espace entre || et &&.

Donc voici un premier code réalisé en 13 min (chrono en main), en même temps que je déjeune :
<?php

header('Content-type: text/plain');

$var = 'smim Gekobox069945282806/Apr/200806/Apr/2008Bonne04345c69e70280||2&&Gekobox069945282806/Apr/200806/Apr/2008Mauva04345c69e70280||3';

function parse ( $var = '' ) {

    if(0 === preg_match('#^smim\s*(.*)$#', $var, $tail))
        return false;

    if(0 === preg_match_all('#(.{7})([0-9]{12})/([a-zA-Z]{3})/([0-9]{6})/([a-zA-Z]{3})/([0-9]{4})(.{5})(.{14})\|\|([^&&]+)#',
                            $tail[1], $matches, PREG_SET_ORDER))
        return false;

    return $matches;
}

$result = parse($var);
if(false === $result)
    echo 'Erreur, et toc !';
else
    print_r($result);
Produira le résultat suivant :

Code : Tout sélectionner

Array ( [0] => Array ( [0] => Gekobox069945282806/Apr/200806/Apr/2008Bonne04345c69e70280||2 [1] => Gekobox [2] => 069945282806 [3] => Apr [4] => 200806 [5] => Apr [6] => 2008 [7] => Bonne [8] => 04345c69e70280 [9] => 2 ) [1] => Array ( [0] => Gekobox069945282806/Apr/200806/Apr/2008Mauva04345c69e70280||3 [1] => Gekobox [2] => 069945282806 [3] => Apr [4] => 200806 [5] => Apr [6] => 2008 [7] => Mauva [8] => 04345c69e70280 [9] => 3 ) )
Tu vois que ton problème se résout effectivement en 2 lignes :).
J'espère que tu remarqueras que c'est autrement plus simple à écrire et à traiter que des substr sur explode sur des list de split ... et j'en passe.

Il faut voir le code comme un exemple pédagogique et pas comme : je te file le code tout chaud dans le bec ;-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Jayden
Invité n'ayant pas de compte PHPfrance

10 avr. 2008, 01:35

Merci. Je comprends maintenant la puissance des expressions régulières. C'est clair que ton aide va me poussé à les étudiées à fond. Vive les expressions régulières!!!
Ce code que je réalise a justement pour but de me permettre d'étudier le php. Donc ne t'inquiète pas ton aide ne fait qu'ajouter à ma soif de connaissance.
Pour la technique que j''utilisais j'ai compris pourquoi ca ne passait pas.C'est parceque quand je récupérais le content les valeurs de mes délimiteurs étaient transformées.
Donc mes "&&" et "II" n'étaient pas reconnu.Par exemple mes / devenait des %2F.D'où mes souci de parsage.
Merci pour votre aide à tous sur ce problème qui est maintenant résolu.