Aggreger valeurs des lignes ayant des champs

Résolu
Decon Messages postés 95 Statut Membre -  
Decon Messages postés 95 Statut Membre -
Bonjour,

Soit le fichier FIC de contenu:
P1:A:TOTO:VAL1:62
P1:A:TOTO:VAL1:56
P1:A:TOTO:VAL2:5
P1:B:TOTO:VAL2:4
P1:A:TITI:VAL1:62
P2:A:TOTO:VAL2:59
P1:B:TITI:VAL6:5
P2:A:TOTO:VAL1:9
P2:B:BLABLA:VAL4:5
P2:B:TOTO:VAL2:61
P2:B:BLABLA:VAL4:51

Je souhaite pourvoir aggréger les lignes du fichier suivant les champs 2,3 et 4. Le séparateur étant ":".

Ce qui devrait me donner le résultat suivant:
A:TOTO:VAL1:127
A:TOTO:VAL2:64
B:TOTO:VAL2:65
B:BLABLA:VAL4:56
A:TITI:VAL1:62
B:TITI:VAL6:5

Merci d'avance.

10 réponses

  1. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    hello
    avec quel outil ? awk ?
    $ awk -F':' '{x[$2, $3, $4]+=$5} END{for (n in x){i=n ; gsub(SUBSEP, FS, n) ; print n FS x[i]}}' fichierFIC  
    A:TITI:VAL1:62  
    B:BLABLA:VAL4:56  
    B:TITI:VAL6:5  
    B:TOTO:VAL2:65  
    A:TOTO:VAL1:127  
    A:TOTO:VAL2:64  
    $  
    0
  2. Decon Messages postés 95 Statut Membre 2
     
    Merci de ta réponse.

    En perl. Je dois l'intégrer à un code perl que j'ai déjà implémenté.

    Sinon, peux tu m'expliquer ce que fait ton script?
    0
  3. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    en utilisant a2p (1) - Awk to Perl translator
    #!/usr/bin/perl
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if $running_under_some_shell;
    			# this emulates #! processing on NIH machines.
    			# (remove #! line above if indigestible)
    
    eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
    			# process any FOO=bar switches
    
    $FS = ':';		# set field separator
    $, = ' ';		# set output field separator
    $\ = "\n";		# set output record separator
    
    while (<>) {
        chomp;	# strip record separator
        ($Fld1,$Fld2,$Fld3,$Fld4,$Fld5) = split($FS, $_, -1);
        $X{$Fld2, $Fld3, $Fld4} += $Fld5;
    }
    
    foreach $n (keys %X) {
        $i = $n;
        ($s_ = '"'.($FS).'"') =~ s/&/\$&/g, $n =~ s/$;/eval $s_/ge;
        print $n . $FS . $X{$i};
    }
    

    $
    0
  4. Decon Messages postés 95 Statut Membre 2
     
    Grand merci dubcek. C'est gentil de ta part.

    Il me reste plus qu'à essayer de comprendre.
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. Decon Messages postés 95 Statut Membre 2
     
    dubcek peux tu m'expliquer à quel niveau t'agrèges les lignes pour que je puisse l'adapter à mon script.
    Ca n'a pas l'air de marcher dans l'état. C'est peut être normal.
    0
  7. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    -F':'      on définit : comme séparateur
    {x[$2, $3, $4]+=$5}        on somme les valeurs du champ 5 dans un tableau indexé par les champs 2, 3 et 4
    END{for (n in x)           pour chaque index n (les 3 champs) du tableau x
    {i=n ; gsub(SUBSEP, FS, n) ; print n FS x[i]}}             on sauve n, on convertit le séparateur des index de tableau ajouté par awk (SUBSEP=\034) en : et on imprime
    0
  8. TMTOWTDI
     
    Trop bavard a2p, ça fait penser à l'enregistrement des macros Excel.

    $ cat aggreger234.pl
    #!/usr/bin/perl
    use strict;use warnings;

    my %aggreger;

    while(<DATA>){
    /^.*?:((?:.*?:){3})(\d+)$/;
    $aggreger{$1} += $2;
    }

    print "$_$aggreger{$_}\n" for sort keys %aggreger;

    __END__
    P1:A:TOTO:VAL1:62
    P1:A:TOTO:VAL1:56
    P1:A:TOTO:VAL2:5
    P1:B:TOTO:VAL2:4
    P1:A:TITI:VAL1:62
    P2:A:TOTO:VAL2:59
    P1:B:TITI:VAL6:5
    P2:A:TOTO:VAL1:9
    P2:B:BLABLA:VAL4:5
    P2:B:TOTO:VAL2:61
    P2:B:BLABLA:VAL4:51

    $ perl aggreger234.pl
    A:TITI:VAL1:62
    A:TOTO:VAL1:127
    A:TOTO:VAL2:64
    B:BLABLA:VAL4:56
    B:TITI:VAL6:5
    B:TOTO:VAL2:65
    0
  9. Decon Messages postés 95 Statut Membre 2
     
    Merci TMTOWTDI.
    Ca marche comme je veux.
    Peux tu cependant m'expliquer ce que tu fais!
    0
  10. TMTOWTDI
     
    Il s'agit de l'utilisation des hash (tableau associatif en perl)
    Dubcek a utilisé aussi un tableau associatif mais en awk.
    La traduction avec a2p n'est pas la manière la plus efficace d'écrire le code en perl selon moi.

    #!/usr/bin/perl
    use strict;use warnings;
    
    my %aggreger; #déclaration de hash
    
    while(<DATA>){                 # utilisation de handle DATA
                                   # pour la lecture des données
      /^.*?:((?:.*?:){3})(\d+)$/;  # séparateur :
                                   # utilisation de ? pour eviter 
                                   # la gourmandise du quantificatuer *
                                   # (?: - ouvre une paranthèse non-capturante
                                   # P1: est donc non capturé
                                   # on capture 3 fois un groupe de 
                                   # n'importe quel caractère 
                                   # jusqu'au 1er : rencontré
                                   # il s'agit des champs 2,3 et 4 avec : inclus
                                   # Ex: A:TOTO:VAL1: pour la 1ère ligne, etc.
                                   # Ca sera la clé de notre Hash ( $1 )
                                   # La 2ème capture ($2) 
                                   # sera la valeur numérique
    
      $aggreger{$1} += $2;         # Sachant que la clé d'un hash est unique
                                   # il suffit d'incrementer sur la clé 
                                   # les valeurs numériques correspondantes
    
    }
    
    print "$_$aggreger{$_}\n" for sort keys %aggreger; # affichage
    
    # DATA lit tout ce qui se trouve après __END__
    
    __END__
    P1:A:TOTO:VAL1:62
    P1:A:TOTO:VAL1:56
    P1:A:TOTO:VAL2:5
    P1:B:TOTO:VAL2:4
    P1:A:TITI:VAL1:62
    P2:A:TOTO:VAL2:59
    P1:B:TITI:VAL6:5
    P2:A:TOTO:VAL1:9
    P2:B:BLABLA:VAL4:5
    P2:B:TOTO:VAL2:61
    P2:B:BLABLA:VAL4:51
    
    0
  11. Decon Messages postés 95 Statut Membre 2
     
    Super! Merci TMTOWTDI.
    0