Ответ 1
$ awk -F"[: \t]+" '{a[$2]+=$NF}END{for(i in a ) print i,a[i] }' file
4 -1
5 10.9
1 1.6
2 4.5
3 5.8
У меня есть файл CSV, из которого я хотел бы извлечь некоторые фрагменты информации: для каждого отдельного значения в одном столбце я хотел бы вычислить сумму соответствующих значений в другом столбце. В конце концов, я могу сделать это на Python, но я считаю, что может быть простое решение с помощью awk
.
Это может быть файл CSV:
2 1:2010-1-bla:bla 1.6
2 2:2010-1-bla:bla 1.1
2 2:2010-1-bla:bla 3.4
2 3:2010-1-bla:bla -1.3
2 3:2010-1-bla:bla 6.0
2 3:2010-1-bla:bla 1.1
2 4:2010-1-bla:bla -1.0
2 5:2010-1-bla:bla 10.9
Я хотел бы получить:
1 1.6
2 4.5
3 5.8
4 -1.0
5 10.9
Пока, я могу извлечь только:
a) значения первого столбца:
awk -F ' ' '{print $(2)}' MyFile.csv | awk -F ':' '{print $(1)}'
а затем получим:
1
2
2
3
3
3
4
5
b) и значения, равные, скажем, 1.1
в последнем столбце:
awk -F ' ' '{print $(NF)}' MyFile.csv | awk '$1 == 1.1'
а затем получим:
1.1
1.1
Я не могу одновременно извлекать колонки, которые меня интересуют, что может помочь мне в конце. Вот пример вывода, который может облегчить вычисление сумм (я не знаю):
1 1.6
2 1.1
2 3.4
3 -1.3
3 6.0
3 1.1
4 -1.0
5 10.9
Edit: Благодаря Elenaher, мы могли бы сказать, что входной файл - это файл выше.
$ awk -F"[: \t]+" '{a[$2]+=$NF}END{for(i in a ) print i,a[i] }' file
4 -1
5 10.9
1 1.6
2 4.5
3 5.8
Это предполагает, что у вас есть два столбца, которые вы показывали раньше: 1 1.1
BEGIN {
last = "";
sum = 0;
}
{
if ($1 != last) {
if (last != "") {
print last " " sum;
}
sum = 0;
last = $1;
}
sum = sum + $2
}
END {
print last " " sum;
}
Итак, предполагая, что ваш ввод выглядит следующим образом:
unique_col, to_sum
1.3, 1 2 3
1.3, 5 6 7
1.4, 2 3 4
Тогда это должно сделать трюк:
$ awk -F, '{ if (seen[$1] == "") { split($2, to_sum, " "); seen[$1] = 0; for (x in to_sum) seen[$1] += to_sum[x]; }} END { for (x in seen) { if (x != "") { print x " " seen[x]; }}}' < input
1.3 6
1.4 9
Для вашего последнего вопроса вы можете использовать split
и одновременно отображать два столбца:
cat filename | awk '{split($2,tab,":"); id = tab[1]; print id " -> " $3;}'
Что печатает:
1 -> 1.6
2 -> 1.1
2 -> 3.4
3 -> -1.3
3 -> 6.0
3 -> 1.1
4 -> -1.0
5 -> 10.9
Для получения полного результата вы можете использовать:
awk -F, '{ split($1,line," "); split(line[2],tab,":"); id=tab[1]; if (sums[id]=="") {sums[id] = 0;} sums[id]+=line[3];} END {for (i=1;i<=length(sums);i++) print i " -> "sums[i]}' < test
который печатает:
1 -> 1.6
2 -> 4.5
3 -> 5.8
4 -> -1
5 -> 10.9
{
b=$2; # assign column 2 to the variable 'b'
sub( /:.*/, "", b); # get rid of everything after the first colon in b
results[b] += $3
}
END { for (result in results )print result " " results[result] }
Если Perl является опцией:
perl -F'(\s+|:)' -lane '$h{$F[2]} += $F[-1]; END{print "$_ $h{$_}" for sort keys %h}' file
выход:
1 1.6
2 4.5
3 5.8
4 -1
5 10.9
Используются следующие параметры командной строки:
-n
цикл вокруг каждой строки входного файла-l
удаляет новые строки перед обработкой и добавляет их обратно-a
режим автосплит - разделение входных строк на массив @F
. По умолчанию разбивается на пробелы.-e
выполнить код perl-F
модификатор авторасширения, в этом случае разбивается на цвет или одно или несколько пробелов. @F
- это массив слов в каждой строке, индексированный начиная с $F[0]
$F[-1]
- последнее слово
Сохранить результат в хеше %h
В END, итерации через отсортированные ключи хеша
Распечатайте каждый элемент $_
и значение хеша $h{$_}