计算文件中每一列的总和


8

在具有以空格''分隔的不同列数的文件中,如何计算列之和。一个例子将表明需要:

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

Answers:


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

用好阵列虽然我认为它可以得到简化为计数之和打印出来的时候了
谢尔盖Kolodyazhnyy

的确,这是最好的答案。
kos 2015年

4

使用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 2015年

@fedorqui echo可以安全地用于回显数字,空白处的$IFS默认值以及应该是数字的值,因此无需处理反斜杠。这个答案的唯一缺点是需要在执行之前知道列数。
kos 2015年

@kos,您永远无法知道输入文件的状态。尽管OP只是提及数字,但总是准备为情况恶化做好准备。请参阅如何逐行(和/或逐字段)读取文件(数据流,变量)?对于宏伟的解释。
fedorqui 2015年

@fedorqui根据您自己的陈述,我认为这是没有讨论的;如果要假设输入文件中可以包含数字以外的内容来说明问题,那么您会遗漏明显的部分:检查读取的内容是否为数字。添加字符串并echo "[...]"用于正确打印您不想输出的内容是没有意义的。
kos 2015年

@kos您当然可以说echo $varand while read a b c,它在这里有效。但是,您会习惯于以较弱的方式编写它,有一天,在处理更复杂的文件时会遇到奇怪的错误。然后,您会注意到引用变量并且使用起来while IFS= read -r ...更安全,并且会说“哦,是的,Fedorqui是正确的,我希望我可以让他抱抱他以表示感谢!”。
fedorqui 2015年

3

从对您自己答案的评论来看,您一次只想要一列的总和。如果是这样,这是一种非确定的方法:

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

您将在其中替换为3您感兴趣的列号。


0

这是一种单行Perl脚本方法。这依赖于使用-aflag,它允许将带有-nflag的当前读取行自动拆分为array @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替换为列号,例如column1:

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

输出为:

8

3
这只会给您一列。您不符合自己的规范。
奥利(Oli)

我没有说我想要所有结果都在同一命令中。加上这个答案,只需要一个循环就可以了
Maythux

那么为什么要投票呢?
Maythux 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.