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

Linux Discussion :

Problème traitement gros fichier plat, cut, sed, etc


Sujet :

Linux

  1. #1
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut Problème traitement gros fichier plat, cut, sed, etc
    Bonjour,

    Voilà, j'ai un problème sur un script que j'ai écrit. Il doit traiter un fichier de 3Go, et selon mes calculs si je laisse ce que j'ai écrit cela mettra 69 jours à s'exécuter ....
    Le fichier est un fichier plat. Chaque ligne contient des infos mises bout à bout.
    ex :
    info1info2l'info3 info4 info5......
    Je dois insérer ces valeurs dans une requête sql pour obtenir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into (xx,xx,xx,...) VALUES ('info1','info2','l\'info3','info4','info5'....)
    Donc, je traite le fichier ligne par ligne.

    - J'utilise le cut pour séparer les champs.
    - Pour chaque champs je lui demande avec un sed de remplacer les ' par \' (Je ne peux pas le faire pour la ligne entière car je me base sur les positions des caractères pour retrouver les champs)
    - Je supprime également grâce au sed, pour chaque champ, les espaces situés en fin de champ.

    ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "INSERT INTO TABLE(xx,xx,xx,xx,xx....) VALUES ('`echo ${ligne} | cut -b 1-14| sed s/\'/\\\\\\\\\'/g | sed s/' '*$/''/g`','`echo ${ligne} | cut -b 15-54| sed s/\'/\\\\\\\\\'/g | sed s/' '*$/''/g`','`echo ${ligne} | cut -b 55-61| sed s/\'/\\\\\\\\\'/g | sed s/' '*$/''/g`','`echo ${ligne} | cut -b 62-67| sed s/\'/\\\\\\\\\'/g | sed s/' '*$/''/g`');" | sed s/\'\'/"null"/g # >> ${FICHIER_REQUETE}
    (en réduit car il y a une centaine de champs au total !)

    Y'aurait-il une solution moins couteuse en temps qui vous viendrait à l'idée ?

    Merci,

    Jérôme

  2. #2
    Membre confirmé Avatar de Tchetch
    Inscrit en
    Mars 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2002
    Messages : 401
    Points : 477
    Points
    477
    Par défaut
    Salut,

    Traiter ça avec un programme en Perl ou en C ne serait pas plus rapide ?

    T.

  3. #3
    Membre éclairé Avatar de Spoutnik
    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 672
    Points : 781
    Points
    781
    Par défaut
    Hello,

    A priori, script perl.
    J'ai fait un script qui fait sensiblement la même chose que toi sur des fichiers plus petits (ordre de 2Mo), c'est de l'ordre de qq secondes.
    La succession des echo | sed me parait couteuse pour pas grand chose.

    ++

    Rq 1 : 3Go de données, tu va mettre des semaines à faire tes insert tu devrais utilser une syntaxe d'import de masse (COPY en PgSQL)
    Rq2 : un certain nombre de SGBDR sont capable d'utiliser directement le format CSV, quel est ton SGBD ? A moins qu'il n'y ai des traitements specifique à faire sur les champs?

  4. #4
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut
    Merci, mais la commande copy ne prend en entrée, que des fichiers avec délimiteurs.
    Si je le génère, j'aurais toujours à faire les cut, et ça prendra toujours autant de temps, non ?

    Jérôme

  5. #5
    Membre éclairé Avatar de Spoutnik
    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 672
    Points : 781
    Points
    781
    Par défaut
    Ca dépend

    quelle est ta base?
    par quel moyen (caractère?) sépare tu tes champs? (par défaut, cut utilise la tabulation, est ce le cas pour toi?).

    Si tu utilise un caratère, la syntaxe pour COPY de Pg :
    COPY tableName [( colonne1 [, colonne2)...]] FROM 'fileName' USING DELIMITERS '\t'.

    En plus, ta commande serait plus efficace avec un awk plutot qu'un cut (un seul passage sur la chaine d'entrée pour faire les séparartions) (en supposant que tu utilise un caractère comme séparateur)

  6. #6
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut
    et ouais ...... mais non ! Je n'utilise pas de caractère séparateur.
    Mes données sont à la suite les unes des autres, et on les retrouve par leur position dans la ligne ...

  7. #7
    Membre éclairé Avatar de Spoutnik
    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 672
    Points : 781
    Points
    781
    Par défaut
    je viens de parcourir un peu plus le man awk, il semble qu'il puisse faire des substr. Ca pourrait peut eutre te servir (plus rapide?)?
    un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cat 'fichier.txt' | awk '{c1=substr($1,indicedebut,longueur); c2=substr($1,indicedebut,longueur); ...... print $c1";"$c2";"$c3 ... }' | psql ....
    Il doit y avoir moyen d'applique le sed (pour virer les espaces finaux) dans le awk, voire avant, mais je ne sais pas comment faire.
    A mon avis, tu devrais regarder plus en détail awk.

    ++

    EDIT : correction du print de la commande

  8. #8
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut
    Ouais. Je vais regarder ça. Merci ;-)

  9. #9
    Membre éclairé Avatar de Spoutnik
    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 672
    Points : 781
    Points
    781
    Par défaut
    Essaye qq chose comme ceci , ca va peut être être plus rapide.

    cat legrosfichier.txt |while read line;
    do
    echo "${line:0:7};${line:8:8};${line:16:5}" |sed -e 's/ *;/;/g' -e 's/ *$//' ;
    done

    le premier sed vire les espaces inutiles en fin de champs (espaces avant le ';') et la deuxième partie vire les espaces en fin de ligne. (y a surement moyen de fusionner les 2).

  10. #10
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut merci
    Merci bien ! En effet ça va plus vite :-)

  11. #11
    Membre éclairé Avatar de Spoutnik
    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 672
    Points : 781
    Points
    781
    Par défaut
    Citation Envoyé par jeromed1
    Merci bien ! En effet ça va plus vite :-)
    cool!!

    tu peux me donner un ordre de grandeur du temps sur ton volume? ca m'interesse

  12. #12
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut
    Hello,
    Ben en fait, ce que je fais maintenant c'est que je crée un fichier csv, que je file ensuite à psql.
    Le problème c'est que j'ai toujours un echo suivi d'un sed dans une boucle sur chaque ligne d'un fichier de 3Go.
    La génération du fichier CSV met 48 à 50h (d'après estimations, je suis en train de tester actuellement)
    Il doit sûrement y avoir un moyen plus rapide, non ?

    Jérôme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    cat $1 | while read ligne 
    do     
        ## on remplace les quotes par des backslash quotes (' par \') et on supprime les espaces de fin de champ et de ligne
        echo "${ligne:0:14};${ligne:14:40};${ligne:54:40};${ligne:94:20};${ligne:114:26};${ligne:140:4};${ligne:144:1};${ligne:145:3};${ligne:148:26};${ligne:174:26};${ligne:200:32};${ligne:232:11};${ligne:243:2};${ligne:245:2};${ligne:247:2};${ligne:249:3};${ligne:252:3};${ligne:255:26};${ligne:281:2};${ligne:283:1};${ligne:284:2};${ligne:286:5};${ligne:291:8};${ligne:299:2};${ligne:301:2};${ligne:303:5};${ligne:308:4};${ligne:312:2};${ligne:314:1};${ligne:315:2};${ligne:317:6};${ligne:323:1};${ligne:324:6};${ligne:330:2};${ligne:332:2};${ligne:334:1};${ligne:335:1};${ligne:336:4};${ligne:340:4};${ligne:344:2};${ligne:346:1};${ligne:347:4};${ligne:351:4};${ligne:355:4};${ligne:359:4};${ligne:363:4};${ligne:367:2};${ligne:369:6};${ligne:375:4};${ligne:379:2};${ligne:381:5};${ligne:386:1};${ligne:387:1};${ligne:388:1};${ligne:389:4};${ligne:393:4};${ligne:397:6};${ligne:403:2};${ligne:405:1};${ligne:406:1};${ligne:407:1};${ligne:408:4};${ligne:412:4};${ligne:416:4};${ligne:420:4};${ligne:424:4};${ligne:428:4};${ligne:432:4};${ligne:436:1};${ligne:437:2};${ligne:439:1};${ligne:440:2};${ligne:442:5}" | sed -e 's/ *;/;/g' -e 's/ *$//' -e s/\'/\\\\\\\'/g >> ${FICHIER_CSV}
    done

  13. #13
    Membre éclairé Avatar de Spoutnik
    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 672
    Points : 781
    Points
    781
    Par défaut
    essaye avec ce script perl, je ne sais pas si ca sera plûs rapide, ni même si ta mémoire ne va pas sauter, mais dans ts les cas, le résultat et les bench m'interessent .

    EDIT : MAJ script : ajout de la fonction trim();
    Fichiers attachés Fichiers attachés

  14. #14
    Futur Membre du Club
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Points : 9
    Points
    9
    Par défaut
    Désolé, mon script est en train de tourner depuis hier matin, je peux plus l'arrêter en si bon chemin.
    Et il doit être écrit en shell.

Discussions similaires

  1. Problème traitement de fichiers texte
    Par darkbol1982 dans le forum VBScript
    Réponses: 7
    Dernier message: 20/02/2009, 15h05
  2. bdd MySQL ==> gros fichier plat, csv
    Par foubou dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 28/04/2008, 15h47
  3. Problème lecture gros fichier texte
    Par UnnamedBoy dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 22/02/2008, 11h13
  4. Traitement gros fichiers
    Par ouiouioui dans le forum Langage
    Réponses: 1
    Dernier message: 18/09/2007, 14h42
  5. générer un fichier xml à partir d'un gros fichier plat
    Par ybennani dans le forum Format d'échange (XML, JSON...)
    Réponses: 7
    Dernier message: 16/05/2007, 10h47

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