ファイルの各列の合計を数える


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

配列を上手に使用すると、単純に合計を数えてすぐに印刷するのが簡単になると思います
Sergiy Kolodyazhnyy

実際、これがここでの最良の答えです。
コス

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入力ファイルがどのようになり得るかを知ることはできません。そしてOPは数字だけを述べていますが、悪いことに備えることは常に良い習慣です。「ファイル(データストリーム、変数)を行ごと(またはフィールドごと)に読み取るにはどうすればよいですか?」を参照してください壮大な説明のために。
fedorqui

@fedorquiあなた自身の声明によると、私はこれは議論の余地がないと考えました。入力ファイルに数字以外のものが含まれている可能性があると想定してポイントを作成したい場合は、露骨な部分が欠けています。読み込まれたものが数字であるかどうかを確認します。文字列を追加echo "[...]"し、出力したくないものを正しく印刷するために使用しても意味がありません。
kos

@kosあなたはもちろん、言うことができるecho $varwhile read a b c、それはここで働きます、。ただし、弱い方法での記述に慣れ、ある日、より複雑なファイルの処理中に奇妙なエラーが発生します。次に、変数の引用と使用の方while IFS= read -r ...が安全であることに気づくでしょう。
fedorqui

3

自分の答えに対するコメントから判断すると、一度に1つの列の合計だけが必要です。もしそうなら、これはそれを行うための非awkの方法です:

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

を、3関心のある列番号に置き換えます。


0

これは、1行の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をcolumn1などの列番号に置き換えます。

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

出力は次のとおりです。

8

3
これは、1つの列だけを取得します。あなたはあなた自身の仕様を満たしていません。
オリ

すべての結果が同じコマンドで欲しいとは言っていません。さらに、この答えはループが必要で完璧です
Maythux

では、なぜ反対票を投じるのでしょうか?
Maythux
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.