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 :

Optimisation lecture fichier via un shell script


Sujet :

Shell et commandes GNU

  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2003
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Optimisation lecture fichier via un shell script
    Bonjour,

    J'ai actuellement un fichier d'entrée de 5 000 000 de lignes environ du type :

    A;B;C;D;E...
    A;B;C;D;F...
    B;C;D;E;F...

    Ce fichier doit être décomposé en sous-fichiers selon une clé définie par exemple les 2 premiers champs et, ce qui est mon pb le plus rapidement possible.

    J'ai essayé en shell script, puis en awk mais les temps de traitement sont toujours trop lents.
    Quelle est la méthode la plus efficace pour effectuer un tel traitement ? et quelle durée puis-je espérer pour effectuer ce traitement ?

    Merci d'avance.

  2. #2
    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
    Es-tu sûr que le code de ton awk est optimisé au maximum ?
    Si ce n'est pas indiscret, peux-tu le mettre en ligne, au cas où

  3. #3
    Futur Membre du Club
    Inscrit en
    Février 2003
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Un extrait du code utilisé :

    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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    #!/usr/bin/ksh
    #set -x
     
    if [ -z "$Col1" ];then Col1=1;fi
    if [ -z "$Col2" ];then Col1=1;fi
    if [ -z "$CptLig" ];then CptLig=0;fi
     
    Nom1="fichier1.out"
    Nom2="fichier2.out"
    Rep=$PWD
     
    calculerNomFichier()
    {
            NomFicSortie="${ColX}${ColY}${ColZ}XXX.txt"
     
    }
     
    writeCorps  ()
    {
            CptLig=$(($CptLig + 1))
            #Structure du corps en sortie
            echo "${Bloc1};${Col4};${Col5};${Bloc2};" >> ${NomFicSortie}
    }
     
    cd ${Rep}
     
    #initialisation Variables de rupture
    IdPrec=""
    MPrec=""
    APrec=""
     
    #Concatenation des 2 fichiers en entrée pour réaliser une boucle de traitement
    Liste="${Nom1} ${Nom2}"
     
    #boucle de traitement des fichiers
    for Nom in ${Liste}
    do
        echo ""
        echo "Traitement de ${Nom} Debut $(date '+%H:%M:%S')"
        echo ""
     
            #Lecture des fichiers en entrée et split des champs par awk
            awk -F"?" '{ print $1,$2,$3,$3,$4,$5,$6 }' $Nom | while read -r Bloc1 Col6 Col7 Coll8 Col9 Col10 Bloc2
            do
                if [ "${IdPrec}" =  "${Col1}" -a  "${Col2}" =  "${Col3}" -a  "${Col4}" =  "${Col5}" ]
                then
                    writeCorps
     
                #Sinon on crée un nouveau fichier, on ecrit :
                #   une ligne d'entete
                #   la 1ere ligne du corps
                else
     
                    #incrément de Num
                    if [ "${IdPrec}" =  "${Col1}" ]
                    then
                        Num=$(($Num + 1))
                        #echo "Incrément du Num à $Num"
                    else
                        Num=1
                    fi
     
                    IdPrec=${Col1}
                    MPrec=${Col2}
                    APrec=${Col3}
                    calculerNomFichier
                    echo "XXX;YYYY${Num}$(echo $(date '+%H%S'));ZZZZ;$(echo $(date '+%d/%m/%Y %H:%M'));${Col4} 6:00-${Col5} 6:00;BBBB;${Col6};AAA;"  > ${NomFicSortie}
                    writeCorps
              fi
        done
    done
     
    echo ""
    echo "Execution `basename $0` terminee at $(date '+%H%M%S') pour $CptLig lignes"
    echo ""
     
    exit 0

  4. #4
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Moi en shell...

    Je verrais bien l'utilisation suivante...

    un cat fic.txt
    un cut -d";" -f1 (pour recuperer toute la 1ere col)
    un cut -d";" -f2 (.....)

    bref...en gros utiliser cut...avec delimiteur ; ou sinon, awk avec delimiteur

  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
    Ce qui est assez coûteux, c'est le double accès sur les données :
    1er par awk
    2ème par "while read"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F"?" '{ print $1,$2,$3,$3,$4,$5,$6 }' $Nom | while read -r Bloc1 Col6 Col7 Coll8 Col9 Col10 Bloc2
    Solution tout en awk qui devrait être plus rapide
    http://www.shellunix.com/awk.html
    http://lea-linux.org/cached/index/Dev-awk.html
    http://pwet.fr/man/linux/commandes/posix/awk


    Obs : ${Col4} et ${Col5} utilisées et pas déclarées...


    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
     
     
    Nom1="fichier1.out"
    Nom2="fichier2.out"
     
    #Concatenation des 2 fichiers en entrée pour réaliser une boucle de traitement
    Liste="${Nom1} ${Nom2}"
     
     
    awk -F"?" -v AAAA=$(date +%H%S) -v script=$(basename $0) '
    function writeCorps()
    {
    	#Structure du corps en sortie
    	# A adapter !!!!!!!!!!
    	print $1";"$4";"$5";"$2";" > NomFicSortie
    }
    BEGIN {
    	IdPrec=""
    	MPrec=""
    	APrec=""
    }
    #------------------------------------------------------------#
    #                      PROCEDURE PRINCIPALE                  #
    #------------------------------------------------------------#
    {
    	if (FILENAME != FILEprec) {
    		print ""
    		TimeStamp="'$(date +%d/%m/%Y_%H:%M)'"
    		print "Traitement de "FILENAME" Debut "TimeStamp
    		print ""
    		FILEprec=FILENAME
    	}
    	if ($1 == IdPrec && $2 == MBrec && $3 == APrec) {
    		# Bloc1 Col6 Col7 Coll8 Col9 Col10 Bloc2
    		writeCorps()
    		next #-- on passe à l enregisrement suivant
    	} 
    	#
    	### Changement de fichier de sortie
    	#
    	if ($1 == IdPrec) {
    		Num=1
    	} else {
    		Num++
    	}
    	IdPrec=$1
    	MPrec=$2
    	APrec=$3
    	NomFicSortie=$1""$2""$3"XXX.txt"
    	TimeStamp="'$(date +%d/%m/%Y_%H:%M)'"
    	print "XXX;YYYY"Num"AAAA;ZZZZ;"TimeStamp";"$4" 6:00-"$5" 6:00;BBBB;"$6";AAA;" > NomFicSortie
    	writeCorps()
     
    }
    #------------------------------------------------------------#
    #                  FIN PROCEDURE PRINCIPALE                  #
    #------------------------------------------------------------#
    END {
    	print ""
    	TimeStamp="'$(date +%d/%m/%Y_%H:%M)'"
    	print "Execution "script" terminee at "TimeStamp" pour "NR" lignes"
    	print ""
    } ' $Liste
     
    exit 0

  6. #6
    Futur Membre du Club
    Inscrit en
    Février 2003
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Merci beaucoup pour tes liens.

    Je suis en cours de tests pour tout exécuter en awk.

    Rq : Pour les Col4 et Col5, j'ai un peu modifié le script avant le post pour ne pas tout afficher d'où quelques pbs non présents dans la version originale.

Discussions similaires

  1. déplacement de fichier via sftp en script ksh
    Par saladin443 dans le forum AIX
    Réponses: 2
    Dernier message: 15/05/2013, 18h21
  2. Optimisation lecture fichier > 3 Mo
    Par Sebastien_INR59 dans le forum Entrée/Sortie
    Réponses: 9
    Dernier message: 21/11/2007, 01h34
  3. Lecture fichier via url ou file, différence ?
    Par kij dans le forum Entrée/Sortie
    Réponses: 28
    Dernier message: 03/01/2007, 13h30
  4. optimiser lecture fichier image
    Par cheho dans le forum C++
    Réponses: 17
    Dernier message: 15/09/2006, 14h14

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