Порахуйте суму кожного стовпця у файлі


9

У файлі з різною кількістю стовпців, розділених пробілом '', Як підрахувати суму стовпців. Приклад показав би необхідність:

File A:

1 2 
2 3
4 5 6 
1 1 1 5

Тоді вихід буде:

  • для стовпця 1 (1 + 2 + 4 + 1) = 8
  • для колонки 2 дорівнює 11
  • для стовпця 3 дорівнює 7
  • для колонки 4 - 5

Відповіді:


12

Використання awk

awk '{for (i=1;i<=NF;i++) sum[i]+=$i;}; END{for (i in sum) print "for column "i" is " sum[i];}' FileA
for column 1 is 8
for column 2 is 11
for column 3 is 7
for column 4 is 5

Хороше використання масивів, хоча я думаю, що це може бути спрощене до просто підрахунку суми та надрукування її відразу
Сергій Колодяжний

Дійсно, це найкраща відповідь тут.
кос

5

Використовуйте numsumдля цього завдання та розділіть між обробкою даних та видачі результатів.

Встановити num-utilsнам потрібноnumsum

sudo apt-get install num-utils

І почніть з

numsum -c <your_file_name>

Приклад

$ cat "File A"
1 2 
2 3
4 5 6 
1 1 1 5

$ numsum -c "File A"
8 11 7 5

або у бажаному форматі:

$ numsum -c "File A" | awk '{for(i=1;i<=NF;i++) {print "for column "i" is "$i}}'
for column 1 is 8
for column 2 is 11
for column 3 is 7
for column 4 is 5

з man numsum

-c      Print out the sum of each column.

приклади з man numsum

EXAMPLES

   Add up the 1st, 2nd and 5th columns only.

       $ numsum -c -x 1,2,5 columns
       15 40 115

   Add up the rows of numbers of a file.

        $ numsum -r columns
        55
        60
        65
        70
        75

3
#!/bin/sh

while read a b c d; do
    col1=$((col1 + a))
    col2=$((col2 + b))
    col3=$((col3 + c))
    col4=$((col4 + d))
done < File_A

echo $col1 $col2 $col3 $col4

Ви, напевно, можете сказати (( col1 += a ))і т. Д. Також echo "..."безпечніше, як іwhile IFS= read -r ...
fedorqui

@fedorqui echoможна безпечно використовувати таким чином, щоб відображати номери, $IFSзначення за замовчуванням у пробілі, і очікується, що це цифри, тому не потрібно мати справу з зворотними косими рисами . Єдиним недоліком цієї відповіді є необхідність знати кількість стовпців до виконання.
kos

@kos ви ніколи не можете знати, яким може бути вхідний файл. І незважаючи на те, що ОП зазначає лише цифри, завжди добре підготуватися до гіршого. Див. Як я можу прочитати файл (потік даних, змінна) по черзі (та / або поле за полем)? для чудового пояснення.
fedorqui

@fedorqui За вашим власним твердженням, я вважав, що це не обговорювалося; Якщо ви хочете зауважити, припускаючи, що вхідний файл може містити щось інше, ніж числа, вам не вистачає кричущої частини: перевірка, чи є прочитане число. Додавання рядків та echo "[...]"правильне друкування того, що ви не хочете виводити, не має сенсу.
кос

@kos Ви, звичайно, можете сказати, echo $varі while read a b cце працює тут. Однак ви звикнете писати це слабко, і одного дня ви отримаєте дивні помилки під час обробки складнішого файлу. Тоді ви помітите, що цитування змінних і використання while IFS= read -r ...було безпечнішим, і ви скажете "о так, fedorqui був правильний, я сподіваюся, що я міг би його обійняти, щоб висловити подяку!".
fedorqui

3

Судячи з коментарів до вашої власної відповіді, вам потрібно лише сума однієї колонки за один раз. Якщо так, то ось непростим способом це зробити:

cut -d' ' -f3 FileA | grep . | paste -s -d+ | bc

де ви б замінили 3номер стовпця, який вас цікавить.


0

Ось однолінійний підхід до сценарію Perl. Це покладається на використання -aпрапора, який дозволяє автоматично розбивати на даний момент прочитаний рядок із -nпрапором на масив @F. Все, що нам потрібно зробити, - це перебрати ці елементи та додати їх до відповідного індексу в $sumмасиві, таким чином, фактично кожен елемент масиву є сумою для кожного відповідного стовпця. Нарешті, ми друкуємо результат у ENDблоці коду.

$ perl -lane '$j=0;foreach $i (@F){$sum[$j]+=$i; $j+=1;}; END{print join("\n",@sum)} ' input.txt                                                     
8
11
7
5

Крім того, ось повний підхід до сценарію Perl. Він покладається на розділення кожного рядка на масив та повторення кожного елемента в цьому масиві, додаючи кожне число до відповідних можливостей у @sumsмасиві. Сценарій роздруковує кожен рядок, після чого створює звіт для кожного стовпця. Друк кожного рядка можна видалити, додавши #попередньоprintf("%s",$line);

#!/usr/bin/env perl
use strict;
use warnings;

open(my $fh,"<",$ARGV[0]); 
my $i = 0;
my @sums;

while(my $line = <$fh>) { 
    printf("%s",$line);
    my @nums = split(" ",$line);
    my $j = 0;
    foreach my $num (@nums){
        $sums[$j] += $num;
        $j += 1;
    }

}

my $k = 0;
foreach my $sum (@sums){
    printf("- column %d sum: %d\n",$k,$sum);
    $k+=1;
}

close($fh);

Використання просте chmod +x ./sum_columns.pl && ./sum_columns.pl input.txt. Наприклад:

$ ./sum_columns_2.pl input.txt                                                                                                                       
1 2 
2 3
4 5 6 
1 1 1 5
- column 0 sum: 8
- column 1 sum: 11
- column 2 sum: 7
- column 3 sum: 5

-2

Просте рішення:

awk '{sum += $i} END {print sum}' file

Замініть i номером стовпця, наприклад, колонка1:

awk '{sum += $1} END {print sum}' file

вихід:

8

3
Це отримує лише один стовпець. Ви не відповідаєте власній специфікації.
Олі

Я не заявив, що хочу, щоб усі результати були в одній команді. плюс ця відповідь просто потребує циклу, і це буде ідеально
Maythux

То навіщо забороняти?
Maythux
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.