Awk условная сумма из файла CSV

У меня есть файл 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, мы могли бы сказать, что входной файл - это файл выше.

Ответ 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

Ответ 2

Это предполагает, что у вас есть два столбца, которые вы показывали раньше: 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;
}

Ответ 3

Итак, предполагая, что ваш ввод выглядит следующим образом:

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

Ответ 4

Для вашего последнего вопроса вы можете использовать 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

Ответ 5

{ 
  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] }

Ответ 6

Если 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{$_}