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 :

[CSV] probleme pour convertir un fichier texte en requete sql


Sujet :

Langage PHP

  1. #1
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 14
    Points : 9
    Points
    9
    Par défaut [CSV] probleme pour convertir un fichier texte en requete sql
    Salut,

    afin de pouvoir faire un import d'un fichier texte dans une table mysql, j'ai besoin de convertir un fichier en csv/requete sql.Je vous mets 2 lignes de ce fichier:

    id=firewall time="2006-07-02 23:59:28" fw="xxx" tz=+0000 startime="2006-07-02 23:57:28" pri=5 slotlevel=2 ruleid=1 srcif="Ethernet1" srcifname="in" ipproto=udp proto=snmp src=10.10.10.10 srcport=2419 dst=10.10.10.10 dstport=161 dstportname=snmp sent=44 rcvd=95 duration=0.00 logtype="connection"

    id=firewall time="2006-07-02 22:32:59" fw="xxx" tz=+0000 startime="2006-07-02 22:30:59" pri=5 slotlevel=2 ruleid=14 srcif="Ethernet0" srcifname="out" ipproto=udp dstif="Ethernet1" dstifname="in" proto=snmp src=10.10.10.10 srcport=2420 dst=10.10.10.10 dstport=161 dstportname=snmp dstname=net_printers sent=43 rcvd=53 duration=0.00 logtype="connection"

    j'ai 2 problemes:
    1) les champs ne sont pas au format csv: j'ai un nom_du_champ=une valeure, avec parfois des "".
    J'ai déjà essayé de faire un script php qui vire les 'nom_du_champ=', mais j'ai un autre probleme:
    2) d'une ligne à l'autre le nombre de champs n'est pas le meme: 20 pour la premiere ligne, 23 pour la seconde.

    pour retomber sur un fichier csv normal, j'ai essayé avec fgetcsv, mais je bloque avec le probleme numéro 2.
    J'ai ensuite essayé avec fscanf, mais c'est tres complexe, surtout à cause du probleme 2

    Pour éviter ca, j'ai essayé (en vain), de faire un script qui me genere une requete sql en fonction du nombre de champ (ex: time=), et me permettant d'avoir un truc du genre:
    $query="INSERT INTO `matable` SET `time`="xxx", etc...";
    la problématique étant que le script doit pouvoir fonctioner sans tenir compte du nombre de champs, sachant que j'aurais une table sql avec le plus de champs possible.

    si vous avez une piste.
    Merci pour votre aide!

  2. #2
    Membre habitué
    Inscrit en
    Janvier 2006
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 140
    Points : 151
    Points
    151
    Par défaut
    une ligne de ton fichier correspond toujours à une ligne dans ta table sql ?

    si c'est le cas :

    - tu fais un file() pour charger ton fichier sous forme de tableau
    - tu exécutes ton script pour virer les "champ="
    - tu fais un explode() sur les espaces
    - tu comptes le nombre maximal d'élement dans chacune des lignes
    - tu définis ta requête de base par rapport à ce nombre max, en mettant automatiquement à vide tous les derniers champs manquants (si nbchamp > nbchampmax).

    Par contre ça marche seulement si tous les champs sont toujours dans le même ordre et si les champs manquants sont toujours A LA FIN de la ligne, c'est à dire qu'il n'en manque pas au milieu...

  3. #3
    Membre habitué
    Inscrit en
    Janvier 2006
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 140
    Points : 151
    Points
    151
    Par défaut
    zut, je viens de voir qu'en fait ce n'était pas le cas... bon et bien dans ce cas il va falloir que tu fasses une extraction de tous les noms de champs (pas juste les enlever) et regarder dans chaque ligne si cette valeur est donnée...

  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    c'est pas tres tres dur... le tout est d'avancer pas a pas.

    * Tu as un enregistrement par ligne (avec une ligne sautée eventuellement ?)
    * Chaque couple champ/valeur est séparé par un espace
    * Certaines valeurs (et toujours celles qui contiennent des espaces) sont entourées de guillemets
    * Le nom des champs et les valeurs sont séparés par =

    donc tu peux t'en sortir avec des expressions regulieres pour recuperer les différents champs (ou un traitement classique de chaine, mais c'est un peu plus chiant)

    et apres generer les requetes qui vont bien avec
    INSERT INTO table (champ1, champ2, champ3) VALUES ('valeur1','valeur2', 'valeur3)

    (et pas INSERT ... SET champ=valeur... ca ca n'existe pas...)

  5. #5
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    Pour l'expression reguliere, essaye qqchose dans ce gout la ;o))

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match_all('# ([^"= ]+)=(")?((?(2)[^"]+|[^ ]+))(?(2)"| )#U', " $ligne ", $tableau)
    A noter que pour que ca marche, il faut l'appliquer sur chaque LIGNE (ca recupere un tableau avec la 1ere case qui contient le nom du champ et la 3eme case qui contient la valeur du champ)

    L'ajout des espaces au debut et a la fin de $ligne est important

  6. #6
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    waouw!
    je m'en vais tester ca!
    n'etant pas un kador en regex, j'allais justement te demander quelle genre d'expression reguliere utiliser
    merci bcp de m'avoir consacré un peu de ton temps!

  7. #7
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    voila mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    $row = 1;
    $handle = fopen("connection_2006_184.log", "r");
    while (($data = fgets($handle, 4096)) !== FALSE) {
     
       preg_match_all('# ([^"= ]+)=(")?((?(2)[^"]+|[^ ]+))(?(2)"| )#U', " $data ", $tableau);
     
       print_r($tableau);
     
       sleep(1);
    }
    fclose($handle);
    ?>
    voila le résultat:
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    Array
    (
        [0] => Array
            (
                [0] =>  id=firewall
                [1] =>  fw="xxx"
                [2] =>  startime="2006-07-02
                [3] =>  pri=5
                [4] =>  ruleid=1
                [5] =>  srcifname="in"
                [6] =>  proto=snmp
                [7] =>  srcport=2414
                [8] =>  dstport=161
                [9] =>  sent=44
                [10] =>  duration=0.00
            )
     
        [1] => Array
            (
                [0] => id
                [1] => fw
                [2] => startime
                [3] => pri
                [4] => ruleid
                [5] => srcifname
                [6] => proto
                [7] => srcport
                [8] => dstport
                [9] => sent
                [10] => duration
            )
     
        [2] => Array
            (
                [0] =>
                [1] =>
                [2] =>
                [3] =>
                [4] =>
                [5] =>
                [6] =>
                [7] =>
                [8] =>
                [9] =>
                [10] =>
            )
     
        [3] => Array
            (
                [0] => firewall
                [1] => "xxx"
                [2] => "2006-07-02
                [3] => 5
                [4] => 1
                [5] => "in"
                [6] => snmp
                [7] => 2414
                [8] => 161
                [9] => 44
                [10] => 0.00
            )
     
    )
    je vais essayer de comprendre la regex afin d'obtenir:
    [0] => id
    [1] => time
    [2] => fw
    [3] => tz
    [4] => startime
    [5] => pri
    [6] => slotlevel
    [7] => ruleid
    [8] => srcif
    [9] => srcifname
    [10] => ipproto
    [11] => proto
    [12] => src
    [13] => srcport
    [14] => dst
    [15] => dstport
    [16] => dstportname
    [17] => sent
    [18] => rcvd
    [19] => duration
    [20] => log_type

    à mon avis le probleme vient de la:
    [2] => startime="2006-07-02
    quand on a un espace entre guillemets.

    Merci encore!

  8. #8
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    essaye de remplacer
    par

  9. #9
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    Array
    (
        [0] => Array
            (
                [0] =>  id=firewall
                [1] =>  fw="fw-FRLTA"
                [2] =>  tz=+0000
                [3] =>  pri=5
                [4] =>  ruleid=1
                [5] =>  srcifname="in"
                [6] =>  ipproto=udp
                [7] =>  src=10.22.252.181
                [8] =>  dst=10.22.37.247
                [9] =>  dstportname=snmp
                [10] =>  rcvd=56
                [11] =>  logtype="connection"
            )
     
        [1] => Array
            (
                [0] => id
                [1] => fw
                [2] => tz
                [3] => pri
                [4] => ruleid
                [5] => srcifname
                [6] => ipproto
                [7] => src
                [8] => dst
                [9] => dstportname
                [10] => rcvd
                [11] => logtype
            )
     
        [2] => Array
            (
                [0] =>
                [1] => "
                [2] =>
                [3] =>
                [4] =>
                [5] => "
                [6] =>
                [7] =>
                [8] =>
                [9] =>
                [10] =>
                [11] => "
            )
     
        [3] => Array
            (
                [0] => firewall
                [1] => fw-FRLTA
                [2] => +0000
                [3] => 5
                [4] => 1
                [5] => in
                [6] => udp
                [7] => 10.22.252.181
                [8] => 10.22.37.247
                [9] => snmp
                [10] => 56
                [11] => connection
            )
     
    )
    la ce coup-ci il ne capte pas startime
    il a l'air de ne capter que ceux qui n'ont pas de "" ou qui n'ont pas d'espace entre les ""
    un vrai casse-tete mon truc :/

  10. #10
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    c'est tout le coeur du probleme ;o)
    en fait, j'ai l'impression que l'expression (?(2) est toujours false surtout... essaye de remplacer :

    par en gardant la précédente modif

    Si ca ne marche toujours pas, il faudra que je fasse des tests chez moi ce soir pour le mettre au point ;o)

    Tu peux aussi essayer d'ameliorer la regexp avec ce lien :
    http://fr.php.net/manual/fr/referenc...ce.conditional

    mais fait attention a ne pas tout casser ;o))

    Encore une chose :
    si dans tes lignes tu as une chaine de caractere qui contient ", je suppose qu'elle s'affichera de telle maniere : champ="valeur\"valeur". Actuellement, ce cas n'est pas géré non plus par la regexp

  11. #11
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    Citation Envoyé par Fladnag
    c'est tout le coeur du probleme ;o)
    en fait, j'ai l'impression que l'expression (?(2) est toujours false surtout... essaye de remplacer :

    par en gardant la précédente modif
    exactement le meme résultat qu'au dessus. J'ai donc au final cette regex:
    preg_match_all('# ([^"= ]+)=("?)?((?(2)[^"]+|[^" ]+))(?(2)"| )#U', " $data ", $tableau);

    Si ca ne marche toujours pas, il faudra que je fasse des tests chez moi ce soir pour le mettre au point ;o)
    ah merci c'est vraiment sympa! tu as besoin de plus d'infos?

    Tu peux aussi essayer d'ameliorer la regexp avec ce lien :
    http://fr.php.net/manual/fr/referenc...ce.conditional

    mais fait attention a ne pas tout casser ;o))
    je vais me documenter et faire une sauvegarde en effet :p

    Encore une chose :
    si dans tes lignes tu as une chaine de caractere qui contient ", je suppose qu'elle s'affichera de telle maniere : champ="valeur\"valeur". Actuellement, ce cas n'est pas géré non plus par la regexp
    ca c'est pas trop grave, le plus important pour moi c'est de bien dissocier champ et valeur, que la valeur soit entourée de "", qu'elle ai un espace entre ses "" ou qu'elle n'ai pas de ""

  12. #12
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    et voila le p'tit script final... j'étais vraiment pas loin ;o)
    En fait il y avait juste l'espace en trop en debut de regexp, ce qui faisait que l'espace final (pris par la précédente regexp) n'était pas pris par la suivante, donc il "sautait" un groupe de champs/valeurs lorsque le précédent n'était pas entouré de guillemets

    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
    27
    28
    <?php
     
    $preg = '#([^"= ]+)=(")?((?(2)[^"]+|[^" ]+))(?(2)"| )#U';
     
    $test = array(
    'id="firewall" time="2006-07-02 23:59:28" fw="xxx" tz=+0000 startime="2006-07-02 23:57:28" pri=5 slotlevel=2 ruleid=1 srcif="Ethernet1" srcifname="in" ipproto=udp proto=snmp src=10.10.10.10 srcport=2419 dst=10.10.10.10 dstport=161 dstportname=snmp sent=44 rcvd=95 duration=0.00 logtype="connection"',
    'id=firewall time="2006-07-02 22:32:59" fw="xxx" tz=+0000 startime="2006-07-02 22:30:59" pri=5 slotlevel=2 ruleid=14 srcif="Ethernet0" srcifname="out" ipproto=udp dstif="Ethernet1" dstifname="in" proto=snmp src=10.10.10.10 srcport=2420 dst=10.10.10.10 dstport=161 dstportname=snmp dstname=net_printers sent=43 rcvd=53 duration=0.00 logtype="connection"',
    );
     
     
    echo "<pre>";
    $listeRequetes=array();
    foreach($test as $texte) {
    	preg_match_all ($preg, " $texte ", $resultats);
     
    	$champs = implode(',', $resultats[1]);
    	$values = "'".implode("','", $resultats[3])."'";
     
    	$listeRequetes[]="INSERT INTO table ($champs) VALUES ($values)";
     
    	echo "<table border=1><tr><td>".implode('</td><td>', $resultats[1])."</td></tr>";
    	echo "<tr><td>".implode('</td><td>', $resultats[3])."</td></tr></table>";
    }
     
    echo implode("<br>", $listeRequetes);
    echo "</pre>";
     
    ?>

  13. #13
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    waaaou
    magnifique ca fonctionne! tu es un dieu!
    Merci bcp!
    tu me retire une grosse épine du pied, et en plus de ca j'ai un cours sur les regex
    encore merci d'avoir donné de ton temps à un parfait inconnu

  14. #14
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    y a pas de quoi ;o)

    j'adore faire des regexp ;o)

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

Discussions similaires

  1. [CSV] convertir un fichier texte formaté en CSV
    Par cotede2 dans le forum Langage
    Réponses: 1
    Dernier message: 20/06/2009, 18h08
  2. Comment faire pour convertir des fichiers csv en série ?
    Par Debutante-Excel dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 31/05/2009, 21h34
  3. Convertir un fichier texte du format csv au format hws
    Par slayer23 dans le forum MATLAB
    Réponses: 8
    Dernier message: 14/06/2007, 17h48
  4. Probleme pour effacer un fichier texte (DeleteFile)
    Par nopnop dans le forum Delphi
    Réponses: 10
    Dernier message: 18/06/2006, 23h47
  5. [VBA-E] Macro pour convertir un fichier texte en excel
    Par Nicolas67 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 15/05/2006, 14h47

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