2011-08-18 3 views
1

J'essaie de trier certaines données dans bash. Les données ressemblent à ci-dessous.tri des données

20110724.gz 1347 
    20110724.gz 2128 
    20110725.gz 1315 
    20110725.gz 2334 
    20110726.gz 808 
    20110726.gz 1088 
    -bash-3.2$ 

Après le tri, il devrait ressembler

20110724.gz 3475 
    20110725.gz 3649 
    20110726.gz 1896 

En fait, pour une date donnée, les données sont résumées. Quelqu'un peut-il aider? Merci.

hmm, j'espère que je l'ai compris dans quelques jours.

Répondre

0

Vous n'avez pas besoin de perl pour le faire. Ruser shell va aider :)

sort -n -k1,8 <file | while true ; do 
    if ! read line ; then 
     test -n "$accfile" && echo $accfile $value 
     break 
    fi 
    line=$(echo $line | tr -s ' ') 
    curfile=$(echo $line | cut -d\ -f1) 
    curvalue=$(echo $line | cut -d\ -f2) 
    if [ $curfile != "$accfile" ] ; then 
     # new file, output the last if not empty 
     test -n "$accfile" && echo $accfile $value 
     accfile=$curfile 
     value=$curvalue 
    else 
     value=$(expr $value \+ $curvalue) 
    fi 
done 

Le paramètre indique k sorte que les caractères utiliser pour trier. Comme les dates sont mises en format numérique, un tri par numéro (-n) fonctionne.

+0

Vous avez manqué la partie sommation. Je ne pense pas que le tri soit suffisant. –

+0

Oups, j'ai raté la partie de sommation! Tu as raison! Voyons voir ... –

+0

Mis à jour. Ce n'était pas facile avec shell seul, mais je voulais passer du temps à me souvenir de mes temps d'or de sh scripting :) –

0

Voici une solution perl.

Utilisation:script.pl input.txt > output.txt

code:

use warnings; 
use strict; 
use ARGV::readonly; 

my %sums; 
while (<>) { 
    my ($date, $num) = split; 
    $sums{$date} += $num; 
} 
for my $date (sort keys %sums) { 
    print "$date $sums{$date}\n"; 
} 

Ou comme une doublure:

$ perl -we 'my %h; while(<>) { ($d,$n)=split; $h{$d}+=$n; } print "$_ $h{$_}\n" for sort keys %h;' data2.txt 

Dans le cas où vous avez besoin d'un tri numérique sur les dates:

sort { substr($a,0,8) <=> substr($b,0,8) } keys %sums; 
1

Voici un oneliner perl rapide et sale:

$ perl -e 'my %h =(); while (<>) { chomp; my ($fname, $count) = split; $h{$fname} += $count;} foreach my $k (sort keys %h) {print $k, " ", $h{$k}, "\n"}' < datafile