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

Shell et commandes GNU Discussion :

Ne prendre que des pavés d'un fichier


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 80
    Par défaut Ne prendre que des pavés d'un fichier
    Bonjour,

    J'ai mis en place un petit algorithme pour résoudre un problème mais je ne sais pas s'il est optimisé.

    Voici un descriptif du problème :

    J'ai un fichier qui se présente ainsi :
    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
    ENTETE AAAA 20101202 0000000003XXXX
    LIGNE1 BBBBBBBBBBB
    LIGNE2 CCCCCCCCCC
    LIGNE3 DDDDDDDDDD
    ENTETE AAAA 20101201 0000000004XXXX
    LIGNE1 EEEEEEEEEEE
    LIGNE2 FFFFFFFFFFF
    LIGNE3 GGGGGGGGGG
    LIGNE4 HHHHHHHHHH
    ENTETE AAAA 20101202 0000000005XXXX
    LIGNE1 IIIIIIIIIIIIIIIIII
    LIGNE2 JJJJJJJJJJJJJJJ
    LIGNE3 KKKKKKKKKKK
    LIGNE4 LLLLLLLLLLLL
    LIGNE5 MMMMMMMM
    1- Je recherche la ligne ENTETE le plus récente. Le champ N°3 est le critère utilisé puisqu'il s'agit d'une date.

    2- A partir du résultat obtenu en "1-", je recherche toutes les ENTETES les plus récentes. Ce qui est équivaut à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ENTETE AAAA 20101202 0000000003XXXX
    ENTETE AAAA 20101202 0000000005XXXX
    3- A partir du résultat obtenu en "2-", je dois extraite les enregistrements associés à cette entete
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ENTETE AAAA 20101202 0000000003XXXX
    LIGNE1 BBBBBBBBBBB
    LIGNE2 CCCCCCCCCC
    LIGNE3 DDDDDDDDDD
    ENTETE AAAA 20101202 0000000005XXXX
    LIGNE1 IIIIIIIIIIIIIIIIII
    LIGNE2 JJJJJJJJJJJJJJJ
    LIGNE3 KKKKKKKKKKK
    LIGNE4 LLLLLLLLLLLL
    LIGNE5 MMMMMMMM
    Pour information, le 4ème champ de l'ENTETE indique ne nombre d'enregistrements associés. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ENTETE AAAA 20101202 0000000003XXXX
    Cela signifie que 3 enregistrements sont associés à cette entete.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ENTETE AAAA 20101202 0000000103XXXX
    Cela signifie que 103 enregistrements sont associés à cette entete.

    Le souci que j'ai, est que je lis plusieurs fois le fichiers en entrée et cela peut être très couteux en terme de perf. Si vous avez une autre idée, je suis preneur.

    Merci d'avance pour votre aide.

    Cdlt

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Dans ce cas de figure, je ne pense pas qu'il existe de solution en shell évitant de parcourir plusieurs fois le fichier.
    Il va falloir passer à du scripting plus évolué (awk, perl, ...) ou carrément à un programme (c, c++, java, ...).

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 718
    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
    #!/bin/bash
     
    while read ent lett date nblines
    do (( date )) && {
          ((date >= newest)) && {
             ((date > newest)) && unset myArr
             newest="$date"
             flag=1
             myArr+=( "$ent $lett $date $nblines" )
          } || flag=0
       } || {
          ((flag)) && myArr+=( "$ent $lett" )
       }
    done <emmachane.in
     
    printf '%s\n' "${myArr[@]}"

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 80
    Par défaut Merci
    Chapeau l'artiste même si je n'ai rien compris au code

    J'ai essayé de l'adapter à mon jeu de données qui lui est un peu plus complexe que l'exemple que j'ai donné en vain

    En réalité, les lignes ne sont pas aussi bien formatées. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ENTETE AAAA 20101202 0000000003XXXX
    n'est pas complète puisque après la chaine 0000000003XXXX, il y a d'autres champs séparés par des espaces

    De plus, la chaine :
    peut contenir plusieurs champs après la chaine BBBBBBBB, également séparés par des espaces.

    Mon objectif n'est pas de vous demander de faire le boulot à ma place. Mais croyez moi, j'ai essayé mais sans succès.

    Quoi qu'il en soit, merci pour votre aide. Vous êtes vraiment des pros !

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 718
    Par défaut
    ce sera peut-être plus clair ainsi:
    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
    #!/bin/bash
     
    while read f1 f2 f3 rest
    do line="$f1 $f2 $f3 $rest"
    # le troisième champs est-il un nombre de 8 chiffres*
       if [[ $f3 =~ ^[0-9]{8}$ ]]
       then if (( f3 >= newest ))
            then (( f3 > newest )) && Array=()
                 newest="$f3"
                 flag=1
                 Array+=( "$line" )
            else
                 flag=0
            fi
       else
          (( flag )) && Array+=( "$line" )
       fi
    done <emmachane.in
     
    printf '%s\n' "${Array[@]}"
    ...
    ?
    * on utilise une regex, mais on pourrait aussi utiliser une évaluation arithmétique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (( date && ${#date} == 8 ))
    mais sans échantillon réellement représentatif de ton fichier

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

Discussions similaires

  1. Renommer des répertoires ainsi que des fichiers
    Par Le POlonais dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 22/11/2007, 22h21
  2. Réponses: 2
    Dernier message: 04/09/2007, 00h06
  3. Réponses: 4
    Dernier message: 07/07/2006, 16h44
  4. Réponses: 5
    Dernier message: 03/02/2006, 00h31
  5. [langage] [PERL] prendre des infos dans un fichier log
    Par osiris73 dans le forum Langage
    Réponses: 2
    Dernier message: 24/05/2005, 17h42

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