Summing up a matrix using awk

Hi there,

If anyone can help me sorting out this small task would be great. Given a matrix like the following:

100     3     3     3     3     3 ...
200     5     5     5     5     5 ...
400     1     1     1     1     1 ...
500     8     8     8     8     8 ...
900     0     0     0     0     0 ...
100     7     7     7     7     7 ...
...

How could I sum, for a given number of rows each time, the the values for all the columns? Say, summing the column values for 2 rows each time. Ending up with a matrix like:

300     8     8     8     8     8
900     9     9     9     9     9
1000   7     7     7     7     7

I'm writing some perl code for the task but I'm courious if the task can be done 'easily' using awk. So far I've just got a flavour on how to sum the all the values for all columns{1} or how to sum all values for a row{2},

i.e {2}

awk '
BEGIN {FS=OFS="\t"}
{
sum=0;
for(i=1;i<=NF;i++)
     {sum+=$i;}
     print sum
}' matrix.txt

Cheers if there's an answer,
J Rodrigo

awk 'NR%2{for (i=1;i<=NF;i++) a+=$i}!(NR%2){for (i=1;i<=NF;i++) {$i+=a;a=0};print}' file

Hi JRodrigoF,

One way:

$ cat infile
100 3 3 3 3 3 
200 5 5 5 5 5 
400 1 1 1 1 1 
500 8 8 8 8 8 
900 0 0 0 0 0 
100 7 7 7 7 7 
$ awk '{ getline line; split( line, fields ); for( i = 1; i <= NF; i++ ) { $i += fields } print }' infile
300 8 8 8 8 8
900 9 9 9 9 9
1000 7 7 7 7 7

Regards,
Birei

Hi bartus11 and birei,

Once again I'm impressed how powerful awk is. Don't understand very well your one-liners but definitely will give myself a proper course and keep practicing,

Cheers guys,
Rodrigo

One-liners are to impress people the power of UNIX.

Let me try to break them down into multi-line with comments so that you can appreciate the real power

awk '
  # for every odd record number (NR) [NR%2 will equate to 1 (true) for odd NR]
  NR%2 {
    # for every field in each record (NF - number of fields)
    for (i=1; i<=NF; i++) {
      # sum them up and store in an associative array 'a', the index i corresponds to the column number
      a+=$i
    }
  }

  # for every even record number (NR) [!(NR%2) will equate to 1 (true) for even NR. ! means 'not']
  !(NR%2) {
    # for every field in each record (NF - number of fields)
    for (i=1; i<=NF; i++) {
      # add the associative array to the original column position
      $i+=a

      # reset assocaite array to zero
      a=0
    }

    # print the whole row after the changes
    print
  }
' file
2 Likes

@Chihung
Thanks for explaining with comment.
This is now readable for amateur for awk like me.