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 :

[ksh] lecture de fichier


Sujet :

Linux

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 31
    Points : 22
    Points
    22
    Par défaut [ksh] lecture de fichier
    Salut à tous,


    Je dois faire un script ksh qui doit faire la chose suivante.

    1 - prendre en paramètres d'entrée un fichier
    2 - compter les lignes de ce fichier
    3 - sélectionner une partie de chaque ligne, qui sont des chiffres, et en faire la somme.



    Vu comme ça, de loin, je m'étais dit "Ok, ça à l'air tout ballot", même si je suis pas spécialisé dans ça.

    Hop, après quelques rafraichissements et des lectures de man et autres docs, j'arrive à faire les étapes 1- et 2-.


    Par contre, à l'étape 3-, là ça part en sucette et je pige pas bien pourquoi.


    Pour le moment, j'ai ça

    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
    #!/bin/ksh
    echo "Nom du fichier traité: $1"
     
    typeset var ligne
    #typeset var montant
     
    NBLIGNE=`awk 'END {print NR}' $1`
     
    echo $NBLIGNE
     
    cat $1 | while read ligne
     
    do
            test=$ligne
            echo $test | cut -c 76-91
    done

    Le fichier en entrée contient des lignes formatées de la même façon.

    Voici son contenu
    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
    EBC_INIT000001  E0593105111   U593              200206001                  000000000000000 000000000000000                                                                                                                                         
    EBC_INIT000001  E0593105111   U593              200212001                  000000000000000 000000000028862                                                                                                                                         
    EBC_INIT000001  E0593105111   U593              200306001                  000000000028862 000000000158512                                                                                                                                         
    EBC_INIT000001  E0593105111   U593              200506001                  000000000158512 000000009353118                                                                                       000000000158512                                   
    EBC_INIT000001  E0593105111   U593              200602001                  000000009353118 000000009353118                                    000000009353118                                                                                      
    EBC_INIT000001  E0593105111   U593              200603001                  000000009353118 000000009353118                                    000000009353118                                                                                      
    EBC_INIT000001  E0593105112   U593              200206001                  000000031310329 000000031100564                                                                                                                                         
    EBC_INIT000001  E0593105112   U593              200212001                  000000031310329 000000031056610                                                                                                                                         
    EBC_INIT000001  E0593105112   U593              200306001                  000000031056610 000000002018306                                                                                                                                         
    EBC_INIT000001  E0593105112   U593              200312001                  000000031056610 000000001823567                                                                                                                                         
    EBC_INIT000001  E0593105112   U593              200406001                  000000001823567 000000001823567                                                                                       000000002018306                                   
    EBC_INIT000001  E0593105112   U593              200412001                  000000001823567 000000001823567                                                                                       000000001823567                                   
    EBC_INIT000001  E0593105112   U593              200506001                  000000001823567 000000000000000                                                                                       000000001823567                                   
    EBC_INIT000001  E0593105112   U593              200512001                  000000001823567 000000000000000                                                                                       000000001823567                                   
    EBC_INIT000001  E0593105113   U593              200206001                  000000000000000 000000000209765                                                                                                                                         
    EBC_INIT000001  E0593105113   U593              200212001                  000000000000000 000000000000000                                                                                                                                         
    EBC_INIT000001  E0593105113   U593              200306001                  000000000000000 000000028908654                                                                                                                                         
    EBC_INIT000001  E0593105113   U593              200312001                  000000000000000 000000029103393                                                                                                                                         
    EBC_INIT000001  E0593105113   U593              200406001                  000000029103393 000000000000000                                                                                       000000028908654                                   
    EBC_INIT000001  E0593105113   U593              200412001                  000000029103393 000000000000000                                                                                       000000029103393                                   
    EBC_INIT000001  E0593105113   U593              200506001                  000000000000000 000000000000000                                                                                       000000000000000                                   
    EBC_INIT000001  E0593105113   U593              200512001                  000000000000000 000000000000000                                                                                       000000000000000                                   
    EBC_INIT000001  E0593105310   U593              200212001                                  000000001174632                                                                                                                                         
    EBC_INIT000001  E0593121992   U593              200702001                  000000000000000 000000000000000                                    000000000000000                                    000000000000000                                   

    On m'a dit dans ma doc: "Extraits les caractères 91 à 106 de chaque ligne"
    Déjà, allez savoir pourquoi, je sias pas comment sont comptés les espaces et/ou tabulation, mais en vrai, ce qui m'intéresse, c'est pas de 91 à 106, mais de 76 à 91 (d'où le cut -c 76-91)


    Donc je lance mon script.

    Et là:

    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
    Nom du fichier traité: EBC_INIT_593.dat
    24
    
    
    
    00000000158512
    00000009353118
    00000009353118
    
    
    
    
    00000002018306
    00000001823567
    00000001823567
    00000001823567
    
    
    
    
    00000028908654
    00000029103393
    00000000000000
    00000000000000
    
    


    Comme vous pouvez le constater, y a des trous et il manque des valeurs.

    Il devrait y avoir au début

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    000000000000000
    000000000028862
    00000000158512
    Or, on passe directement à



    Idéalement, ca devrait me donner ça

    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
    Nom du fichier traité: EBC_INIT_593.dat
    24
    000000000000000
    000000000028862
    000000000158512
    000000009353118
    000000009353118
    000000009353118
    000000031100564
    000000031056610
    000000002018306
    000000001823567
    000000001823567
    000000001823567
    000000000000000
    000000000000000
    000000000209765
    000000000000000
    000000028908654
    000000029103393
    000000000000000
    000000000000000
    000000000000000
    000000000000000
    000000001174632
    000000000000000
    
    Et en fait, ça me donne ça

    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
    Nom du fichier traité: EBC_INIT_593.dat
    24
    
    
    
    00000000158512
    00000009353118
    00000009353118
    
    
    
    
    00000002018306
    00000001823567
    00000001823567
    00000001823567
    
    
    
    
    00000028908654
    00000029103393
    00000000000000
    00000000000000
    
    

    Donc voilà, je comprends pas.

    Si quelqu'un à une idée, ca serait super.

  2. #2
    Expert éminent sénior Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Points : 12 262
    Points
    12 262
    Par défaut
    ajoutes un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ................................| grep -v ^$
    ca devrait éliminier les lignes vides optenues.

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 31
    Points : 22
    Points
    22
    Par défaut
    Citation Envoyé par frp31
    ajoutes un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ................................| grep -v ^$
    ca devrait éliminier les lignes vides optenues.


    Alors j'ai fait ça et .... :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Nom du fichier traité: EBC_INIT_593.dat
    24
    00000000158512
    00000009353118
    00000009353118
    00000002018306
    00000001823567
    00000001823567
    00000001823567
    00000028908654
    00000029103393
    00000000000000
    00000000000000



    Effectivement, en gros c'est le résultat que j'avais avant, mais sans les gros vides. Cool.
    Or c'est pas "virer les gros vides" qui m'intéressent, mais "les remplir avec ce qui devraient y avoir".

    Car il me manque toujours ce qui est en italique ci-dessous

    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
    Nom du fichier traité: EBC_INIT_593.dat
    24
    000000000000000
    000000000028862
    000000000158512
    000000009353118
    000000009353118
    000000009353118
    000000031100564
    000000031056610
    000000002018306
    000000001823567
    000000001823567
    000000001823567
    000000000000000
    000000000000000
    000000000209765
    000000000000000
    000000028908654
    000000029103393
    000000000000000
    000000000000000
    000000000000000
    000000000000000
    000000001174632
    000000000000000



    En fait, ça a juste compressé en un seul bloc le résultat erroné et plein de trous de mon script.

    :'(

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 27
    Points : 27
    Points
    27
    Par défaut
    je comprend pas car chez moi si je copie/col ton fichier fichier data dans data.txt
    et si je fait juste en bash un " wc -l data.txt ; cat data.txt |cut -c 91-106 " j'obtient le bon resultat.

    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
     
     wc -l data.txt ; cat data.txt |cut -c 91-106
    24 data.txt
     000000000000000
     000000000028862
     000000000158512
     000000009353118
     000000009353118
     000000009353118
     000000031100564
     000000031056610
     000000002018306
     000000001823567
     000000001823567
     000000001823567
     000000000000000
     000000000000000
     000000000209765
     000000000000000
     000000028908654
     000000029103393
     000000000000000
     000000000000000
     000000000000000
     000000000000000
     000000001174632
     000000000000000

  5. #5
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Peut-être y a-t-il des caractères parasites non visibles
    Pour voir si c'est le cas, essaye :

    cat -A {nom_de_fichier}

    ou

    od -a {nom_de_fichier}

  6. #6
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 31
    Points : 22
    Points
    22
    Par défaut
    ALors, j'ai testé vos trucs.

    Et ça marche \o/

    Mon code en est là.

    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
     
    #!/bin/ksh
     
    typeset var tmp
    typeset -i montant=0
     
    touch tmp.dat
     
    NBLIGNE=`wc -l $1`
    echo $NBLIGNE
     
    cat -q $1 |cut -c 91-106 > tmp.dat
     
     
     
     
    while read ligne
    do
            tmp=`expr $ligne`
            montant=$tmp+$montant
    done < tmp.dat
     
    echo $montant
    rm tmp.dat
    En gros, je récupère ma colonne comme il faut, je transforme ça en numérique et j'en fais la somme.

    Par contre, je me demandais si on pouvait pas optimiser le traitement.

    Là, ok, c'est du temporaire, je fais des tests dessus, mais si vous regradez bien,

    - je parcours mon fichier en entrée pour en extraire ce que je veux
    - je copie le résultat extrait dans un tmp.dat
    - j'additionne ce qu'il y a dans le tmp.dat
    - j'affiche le montant.

    En gros, je parcours 2 fois des fichiers: une fois le fichier en entrée ET je parcours le tmp.dat pour faire ma somme.

    Est ce que je pourrais pas faire d'un coup, lors du parcours du fichier en entrée:

    Extraction de la partie qui m'intéresse ET transformation en numérique ET faire mon addition puis passer passer à la ligne suivante ?

    Ca me ferait qu'un parcours, sans avoir à faire une copie temporaire tmp.dat

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 27
    Points : 27
    Points
    27
    Par défaut
    une version en bash un peu bourrine , mais en une seule passe.

    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
     
    #!/bin/bash
     
    montant=0
    NBLIGNE=0
     
    cat $1 |cut -c 91-106| while read ligne;
    do     
       NBLIGNE=$(($NBLIGNE+1))   
       montant=`expr $ligne + $montant`
       echo "lignes:$NBLIGNE montant:$montant" > fic.tmp   
    done 
     
    cat fic.tmp
    rm fic.tmp

  8. #8
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    L'option -q de la commande cat, je ne connais pas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #!/bin/ksh
     
    typeset -i total=0
    NBLIGNE=`wc -l $1`
    echo $NBLIGNE
     
    for montant in `cat -q $1 |cut -c 91-106` 
    do
    	echo "* $montant"
    	((total=total+montant))
    done
    echo "* $total"

  9. #9
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 31
    Points : 22
    Points
    22
    Par défaut
    Salut !


    Encore une fois, j'ai testé vos trucs et ça marche pas mal.


    J'ai peaufiné mon script pour l'adapter à mes besoins et le tester en grandeurs natures.


    Par contre, quand je lui balance des fichiers énormes à traiter, il me balance une erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    integrite_fichiers.ksh[34]: no space
    Alors, apparemment, ça vient pas du code en lui-même, mais par contre, je me demande si ça vient pas du fait que je me retrouve avec des montants de psychopathes, quand je traite un fichier de plusieurs milllions de lignes.

  10. #10
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Citation Envoyé par KuBi4K
    Salut !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    integrite_fichiers.ksh[34]: no space
    Alors, apparemment, ça vient pas du code en lui-même, mais par contre, je me demande si ça vient pas du fait que je me retrouve avec des montants de psychopathes, quand je traite un fichier de plusieurs milllions de lignes.
    lance ton script avec l'option trace comme suit :



    Pour te répondre, il est souhaitable de montrer la trace de la partie qui plante

  11. #11
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 31
    Points : 22
    Points
    22
    Par défaut
    Citation Envoyé par BlaireauOne
    lance ton script avec l'option trace comme suit :



    Pour te répondre, il est souhaitable de montrer la trace de la partie qui plante

    comprends pas ce que tu veux que je te file....

    Le log du sh -x, aka des milliers de lignes ?

  12. #12
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Citation Envoyé par KuBi4K
    comprends pas ce que tu veux que je te file....

    Le log du sh -x, aka des milliers de lignes ?

    integrite_fichiers.ksh[34]: no space : ça doit bien correspondre au résultat d' une instruction.
    Si tu veux de l'aide, le minimum c'est de communiquer la trace de cette instruction

  13. #13
    Membre chevronné

    Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 296
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 296
    Points : 1 803
    Points
    1 803
    Par défaut
    quel est la ligne de code 34 ?

    si tu utilise la solution avec un for cela peut être un trop grand nombre de ligne ! :
    for i in $(cat .........)
    le shell résout AVANT la boucle le cat et sur plusieurs milliers de ligne .... no space left !
    donc preferer la forme
    while read ligne
    do
    ....
    done < fichier
    ou
    cat fichier | while read ligne (uniquement si le "tampon" du pipe est de taille suffisante (voir ulimit -a)

  14. #14
    Membre à l'essai
    Inscrit en
    Juin 2005
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 31
    Points : 22
    Points
    22
    Par défaut
    Salut, me revoilà après un petit RTT privé d'Internet :p

    J'ai trouvé la solutiion à mon problème

    J'utilisais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for montant in `cat -q $1 |cut -c 91-106`
    proposé par BlaireauOne.

    En fait, d'après ce que j'ai pu comprendre et de ce qu'a confirmé un collègue qui passait par là (il m'avait pas dit qu'il avait déjà fait du script Unix, le fourbe...), le problème venait du fait que pour la portion de code que j'ai cité, j'explosais la mémoire de la bécane.

    Du coup, j'ai changé un peu, j'ai forcé la lecture ligne à ligne PUIS, le cut après.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    while read ligne
    do
     
           ligne_lue=`echo "$ligne\n" | cut -c 91-106
     
    done < $mon_fichier
    Et là, ça marche \o/

    Merci à tous et en route pour de nouvelles aventures !



    EDIT: Confirmé par le reply précédent que j'avais pas vu, car page non rafraichie \o/

  15. #15
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 23
    Points : 17
    Points
    17
    Par défaut Faire un CUT d'une ligne avec espace/tabulation
    Salut, j'ai pas lu à 100% tout le post, mais je voulais juste ajouter un petit point sur lequel j'ai buté cette semaine en voulant faire un script du genre.

    Il y a une différence majeure quand on fait un echo d'une variable entre doublequote(") et quand on le fait sans.

    En effet, si on met les doublequote, ca garde le formattage des tabulations et espaces, sinon ca tronque à un espace et dans ce dernier cas, lorsqu'on joint ca à un CUT sans avoir mis les doublequote, alors cela à un effet désastreux sur le résultat choisi...

    C'est pour ca qu'il faut faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne_lue=`echo "$ligne\n" | cut -c 91-106
    et non un echo de $ligne sans les double quotes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne_lue=`echo $ligne\n | cut -c 91-106

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

Discussions similaires

  1. [KSH] lecture et comparaison de deux fichiers
    Par ManusDei dans le forum Shell et commandes GNU
    Réponses: 9
    Dernier message: 28/09/2012, 13h52
  2. Réponses: 1
    Dernier message: 12/04/2010, 15h15
  3. [ksh] Lecture d'un fichier unicode ligne par ligne
    Par Arnaud F. dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 30/07/2008, 21h46
  4. Lecture de fichier
    Par Watcha dans le forum x86 16-bits
    Réponses: 13
    Dernier message: 04/03/2003, 21h43
  5. Lecture de fichiers ".WAV"...
    Par 0x4e84 dans le forum Langage
    Réponses: 2
    Dernier message: 03/09/2002, 10h43

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