J'ai rencontré un problème qui dépasse mes connaissances unix de base et j'apprécierais vraiment de l'aide. J'ai un grand file dans le format suivant:
2 1019 0 12 2 1019 3 0 2 1021 0 2 2 1021 2 0 2 1022 4 5 2 1030 0 1 2 1030 5 0 2 1031 4 4
Si les valeurs de la colonne deux correspondent, je veux additionner les valeurs des colonnes 3 et 4 des deux lignes, sinon seulement la sum des valeurs de la ligne unique.
Donc, la sortie que j'espère ressemblera à ceci:
2 1019 15 2 1021 4 2 1022 9 2 1030 6 2 1031 8
Je suis capable de sortinger les files selon la colonne 2 avec awk ou de sortinger et de sumr les dernières colonnes avec awk, mais seulement pour les lignes individuelles pas pour deux lignes où la colonne 2 correspond.
Je ferais ça en Perl:
$ perl -lane '$k{"$F[0] $F[1]"}+=$F[2]+$F[3]; END{print "$_ $k{$_}" for keys(%k) }' file 2 1019 15 2 1021 4 2 1030 6 2 1031 8 2 1022 9
Ou awk:
awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file
Si vous voulez que la sortie soit sortingée selon la deuxième colonne, vous pouvez simplement sort
pour sort
:
awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file | sort -k2
Notez que les deux solutions incluent également la 1ère colonne. L'idée est d'utiliser les première et deuxième colonnes comme keys d'un hachage (en perl) ou d'un tableau associatif (en awk). La key de chaque solution est column1 column2
donc si deux lignes ont la même colonne deux mais une colonne différente, elles seront regroupées séparément:
$ cat file 2 1019 2 3 2 1019 4 1 3 1019 2 2 $ awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file 3 1019 4 2 1019 10
Peut-être que cela pourrait aider, mais la colonne 1 est-elle toujours 2 et les résultats en dépendent-ils?
awk '{ map[$2] += $3 + $4; } END { for (i in map) { print "2", i, map[i] | "sort -t't'" } }' file
ou comme mentionné par glenn jackman dans les commentaires sur le sorting:
gawk '{ map[$2] += $3 + $4; } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (i in map) { print 2, i, map[i] } }' file
Vous pouvez pré-sortinger datatables et laisser awk gérer les détails:
sort -n infile | awk 'NR>1 && p!=$2 {print p,s} {s+=$3+$4} {p=$2}'
Sortie:
1019 15 1021 19 1022 28 1030 34
Si vous voulez vraiment garder la première colonne, faites quelque chose comme ceci:
sort -n infile | awk 'NR>1 && p!=$1FS$2 {print p,s} {s+=$3+$4} {p=$1FS$2}'
Sortie:
2 1019 15 2 1021 19 2 1022 28 2 1030 34
La variable p
contient la valeur $2
de la ligne précédente, ou $1FS$2
dans le deuxième cas ci-dessus. Cela signifie que le {print p,s}
est déclenché quand $2
de la ligne précédente n'est pas la même que celle de la ligne courante ( p!=$2
).