This question already has an answer here:

I am new to unix(just a week into it), i have problem there are two files




one is an output file and another an input file

If the values in column 2 match, I want to sum the values in column 3 and 4 of both lines, else just the sum of the values in column 3 and 4 in the unique line for both input and output and compare the values of the total(3rd and 4th) and if diffrent raise a message with the value of 2nd column for which the sum is not matching

Total of

1019 15
1021 4
1022 9
1030 6
1031 8

in input

Total of

1019 25
1021 24
1022 19

in output

Expected output 
Unequal total for 1019,1021,1022

Note: The values in input and output are pipe(|) seperated

Ran this script

awk -F '|' '{Arr[$2]=Arr[$2]+$3+$4}END{ for(i in Arr)print "amount for planId " i " is :"Arr[i]}'

on first file and got this output

amount for planId  is :0
amount for planId 1019 is :12
amount for planId 1021 is :4
amount for planId 1022 is :9
amount for planId 1030 is :6
amount for planId 1031 is :8

dont know why the first line comes

amount for planId  is :0

marked as duplicate by Thomas Nyman, Satō Katsura, countermode, Tomasz, thrig Feb 24 '17 at 15:10

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


Another awk approach:

$ awk 'NR==FNR{a[$2]+=$3+$4; next} {b[$2]+=$3+$4;}
           for(i in a){
             if(i in b && a[i]!=b[1]){
                print "Unequal total for",i
       }' input output 
Unequal total for 1019
Unequal total for 1021
Unequal total for 1022

Or, if you really need the exact output you show in your question:

$ awk 'NR==FNR{a[$2]+=$3+$4; next} {b[$2]+=$3+$4;}
            for(i in a){
                if(i in b && a[i]!=b[1]){
            printf "Unequal total for "; 
            for(i in c){printf "%s, ", i}
        }' input output | perl -pe 's/,\s*$/\n/'
Unequal total for 1019, 1021, 1022

FNR is the current file's line number and NR is the overall line number of all input. The two are equal only while the first file is being read. So, NR==FNR{a[$2]+=$3+$4; next} will add the sum of the 3rd and 4th column, to the value associated with the 2nd column in the array a, and do so only for the first file. The next ensures that we move to the next line and don't execute the rest of the script for the current line.

The {b[$2]+=$3+$4;} will only be run if the previous one wasn't, if we're reading the second file. It does the same thing for the values in the second file, except it saves them in the array b.

Once we reach the end of all input, the END{} block is executed. This will iterate over all keys in a and, if they are also keys in b, and their value is not the same, it prints out the key.

  • How will it handle the pipe(|) separated data ? – CoderAkki Feb 24 '17 at 9:18
  • @CoderAkki it won't. Your question doesn't have pipe separated data. If that's what you need add -F"|" to the command: awk -F"|" . . . . – terdon Feb 24 '17 at 9:23
  • Ya I too tried the same – CoderAkki Feb 24 '17 at 9:29
  • Thanks for the explanation, doing things without knowing is not good code of conduct – CoderAkki Feb 24 '17 at 9:32
  • @CoderAkki indeed. By the way, if one of the answers you received solved your issue, please take a moment and accept it by clicking on the check mark to the left. That will mark the question as answered and is the way thanks are expressed on the Stack Exchange sites. – terdon Feb 24 '17 at 9:42

first 2 awk commands are used to add the values and redirect the output to f1.out and f2.out

final one is to compare the values between f1.out and f2.out

$ awk '{Arr[$2]=Arr[$2]+$3+$4}END{for(i in Arr)print i,Arr[i]}' file1 > f1.out
$ awk '{Arr[$2]=Arr[$2]+$3+$4}END{for(i in Arr)print i,Arr[i]}' file2 > f2.out
$ awk 'NR==FNR{Arr[$1]=$2;next}{if(Arr[$1]!=$2){out=$1","out;}}END{print out}' f1.out f2.out

Not the answer you're looking for? Browse other questions tagged or ask your own question.