0

I have a file with values, some are whole numbers & some are with decimals

# cat file    
value1 100
value2 500.10
value3 2505
value4 35.4

I want to divide each value in field2 with say a fixed number=1000, also sum all values after division. resulting values must carry 5 digits after decimals

# cat output.txt
value1 100 0.10000
value2 500.10 0.50010
value3 2505 2.50500
value4 35.4 0.03450
sum   3140.50000 3.14050   
6
  • 2
    Why must you use awk? Is this homework?
    – waltinator
    Apr 17 at 15:06
  • @waltinator: what would you use besides awk for this?
    – jesse_b
    Apr 17 at 15:09
  • 2
    Perl, Matlab, a spreadsheet... there are other tools besides awk
    – roaima
    Apr 17 at 15:48
  • You've asked and received answers to several awk questions recently so you must've picked up at least a little about awk - please edit your question to show your attempt to solve the problem yourself.
    – Ed Morton
    Apr 18 at 11:45
  • @roaima my point was there is nothing strange about asking for an awk solution for this. If the CLI is being used awk is the correct tool for the job. If OP had said "without using awk" then it would seem like a homework question.
    – jesse_b
    Apr 18 at 12:01

3 Answers 3

5

I believe your sum values are off but you could use the following:

{
        div = $2 / 1000
        sum += $2
        divsum += div
        printf "%s %.5f\n", $0, div
}

END {
        printf "sum %.5f %.5f\n", sum, divsum
}

$ awk '{div=$2/1000;sum+=$2; divsum+=div; printf "%s %.5f\n", $0, div}END{printf "sum %.5f %.5f\n", sum, divsum}' file
value1 100 0.10000
value2 500.10 0.50010
value3 2505 2.50500
value4 35.4 0.03540
sum 3140.50000 3.14050
1
4

Basically the same idea as @jesse_b's answer, but with one less intermediate variable:

$ awk '{ sum+=$2; dsum+=$3=$2/1000; print} END{print "sum",sum,dsum}' file 
value1 100 0.1
value2 500.10 0.5001
value3 2505 2.505
value4 35.4 0.0354
sum 3140.5 3.1405

You can use printf if you need more precision:

$ awk '{ 
        sum+=$2; dsum+=$3=sprintf("%.5f",$2/1000); print 
    } 
    END{printf "%s%s%.5f%s%.5f\n", "sum",OFS,sum,OFS,dsum}' file 
value1 100 0.10000
value2 500.10 0.50010
value3 2505 2.50500
value4 35.4 0.03540
sum 3140.50000 3.14050

And here's a Perl way, for fun:

$ perl -lane '$sum+=$F[1]; $dsum+=$F[2]=sprintf("%.5f",$F[1]/1000);
              print "@F"; }{ print "sum $sum $dsum"' file 
value1 100 0.10000
value2 500.10 0.50010
value3 2505 2.50500
value4 35.4 0.03540
sum 3140.5 3.1405

And, with greater precision:

$ perl -lane '$sum+=$F[1]; $dsum+=$F[2]=sprintf("%.5f",$F[1]/1000); 
              print "@F"; }{ 
              printf "sum %.5f %.5f\n", $sum, $dsum' file 
value1 100 0.10000
value2 500.10 0.50010
value3 2505 2.50500
value4 35.4 0.03540
sum 3140.50000 3.14050
1
  • 3
    @αғsнιη sure, OK, I made the perl that way too. And yes, }{ in Perl is shorthand for END{}. You can write perl 'whatever; END{something}' or perl 'whatever; }{ something'.
    – terdon
    Apr 17 at 16:00
2

Here's one way using the GNU desk calculator dc , a command line RpN calculator.

sed -E 's/\S+/[&]/' file |
dc -e "
##> final sums displayed
[
  [Sum]nlyx
  lpd1/nlyx
  lzxq
]sq

##> output each line read
[
  rnlyx
  dd lp+sp nlyx
  lzx
]sa

##> main() to read , process, & print each lineread
[?z0=q lax cz0=?]s?

## > helper macros to pad leading zero for numbers < 1
[0n]s0 [9an]sy
[1000/ddZrX!<0p]sz

##> set precision and start
5kl?x
" - | column -ts$'\t'
value1  100         0.10000
value2  500.10      0.50010
value3  2505        2.50500
value4  35.4        0.03540
Sum     3140.50000  3.14050

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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