0

I've to make a script which will be able to sum the columns. The file looks like that:

1 2 3
1 2 
1

While executing script without the argument ./sum.sh I get the sum of all the columns so the answer is 10. But I have to make it add only certain columns. For example ./sum.sh 1 3 should sum first and third column and give 6.

My code:

sum=0

if [[ $# -eq 0 ]]; then
  awk '{for(i=1;i<=NF;i++) sum+=$i;}; END {print sum}' plik.txt
  else
    exit 0;
fi

while [ $# -gt 0 ]
do
    awk '{sum +="$1"} END {print sum}' plik.txt
    shift
done

I think that I'm quite close to the solution, but something must be missing.

3
  • There's a good solution here without using awk: stackoverflow.com/questions/33006845/… , If you are planning on doing such thing it might be better to let awk determine if there's one argument or more per line. Commented Dec 15, 2016 at 13:14
  • But I have to do it using awk. I know that this while chunk of code is not so bad but there is only a small part that I'm missing to achieve what I want. Commented Dec 15, 2016 at 13:16
  • The solution I provided doesn't print per line, if you want the sum to be calculated per line I need to make some small changes. Commented Dec 15, 2016 at 13:26

3 Answers 3

2

This one liner should work:

awk -v c="1 3" 'BEGIN{split(c,cols)}
               {for(x in cols)s+=$cols[x]}END{print "Sum:"s}' file

Note the c="1 3" means the columns you want to do sum, space separated. It could be set by shell script variable: -v c="$var", the awk will do the calculation and output.

With your example file, the above one-liner outputs:

Sum:6
Sign up to request clarification or add additional context in comments.

4 Comments

it works but I was hoping for minor upgrade of what I posted using shift.
@codddeer123 you don't need shift, just gather all the parameter, and build the a b c d string, and pass to the awk line
I came up with something like this: while [[ $# -gt 0 ]] do awk -v x="$1" '{sum +=$x} END {print sum}' plik.txt shift done and after executing ./sum.sh 1 2 it returns 3 and 4 so it adds up first and second column. How to add them together and get the final answer?
@codddeer123 read my comment above, "you don't need the shift"
1

here is a combination of your script and Kent's solution

#!/bin/bash

file=plik.txt

if [ $# -eq 0 ];
    then
        awk     '{for(i=1;i<=NF;i++) sum+=$i} 
             END {print sum}' "$file"
    else
        awk -v cols="$*" 'BEGIN {split(cols,cs)}
                                {for(c in cs) sum+=$cs[c]}
                          END   {print sum}' "$file"    
fi

in action

$ ./sum.sh 1
3

$ ./sum.sh
10

$ ./sum.sh 1 3
6

$ ./sum.sh 1 2
7

$ ./sum.sh 1 2 3 4
10

$ ./sum.sh 1 2 3
10

Comments

0

This is what I came up with, no bash conditions required:

awk 'BEGIN{sum=0} {if(NF==1) sum+=$1;else for(i=1;i<=NF;i++) sum+=$i;} END{print sum}' plik.txt

3 Comments

./sum.sh 3 returns 10 and ./sum.sh 2 also returns 10 so it doesn't work. I has to sum only certain columns as I mentioned. ./sum.sh 1 3 should add up first and third column of plik.txt file
What do I do in a case that a column does not exist?
hmm, script can exit with info about not correct argument but for now I only want to sum chosen columns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.