How to print float numbers with awk

Viewed 941

I have this input file:

Adrian 20.6
Bruce 40.2
Adrian 30.4
Janick 24.2
Dave 42.7
Bruce 42.9
Janick 41.2

And with a answer I've got here, I was able to sum the numbers, but now the numbers are float and I don't know how to print them.

For now, my output is:

Adrian 50
Bruce 82
Dave 42
Janick 65

But it should be with the decimals as well.

$(awk '{sum[$1] += $2} END {for (i in sum) print i, sum[i]}' $arq > temp.txt && sort temp.txt)

I've made that code to sort by alphabetical order.

2 Answers

You're in a locale where the decimal separator is not . so the . is being treated as any other character that's not part of a number (e.g. a or @) and so your numbers are being truncated to the part before the ..

Do LC_ALL=C awk '...' to set your locale to one that does use a . for the decimal separator and then your script will work as-is.

I think you are closer than you think, but your problems stem from not handling putting the pieces together in the right order. By default awk handles floating-point math. Your summation of sum[$1] += $2 will be done with floating point numbers if your input numbers contains decimal places.

Why you are using a Command Substitution, e.g. $(..) is unclear. That isn't needed to fill temp.txt with the sorted sums from your input. Let's take for example your input file in a file named input. Then to sum and output the values you need nothing more than:

awk '{sum[$1] += $2} END {for (i in sum) print i, sum[i]}' input

Which results in the output of:

Bruce 83.1
Dave 42.7
Adrian 51
Janick 65.4

To sort the results, simply pipe the awk output to sort, e.g.

awk '{sum[$1] += $2} END {for (i in sum) print i, sum[i]}' input | sort

Result:

Adrian 51
Bruce 83.1
Dave 42.7
Janick 65.4

Now, to fill temp.txt, you simply need to redirect the output to temp.txt, e.g.

awk '{sum[$1] += $2} END {for (i in sum) print i, sum[i]}' input | sort > temp.txt

temp.txt now contains the sorted output. To nicely tabularize the output, you can format the output by saving the max length for $1 and setting the name field-width to max and then outputting the floating-point number in a fixed format (total floating-point field-width 10 with 1 digit following the decimal point), e.g.

{sum[$1] += $2; len=length($1); if(len>max)max=len} ...  printf "%-*s%10.1f\n", max, i, sum[i]

Or in full-form:

awk '{sum[$1] += $2; len=length($1); if(len>max)max=len} END {for (i in sum) printf "%-*s%10.1f\n", max, i, sum[i]}' input | sort > temp.txt

With the results in temp.txt now being:

$ cat temp.txt
Adrian      51.0
Bruce       83.1
Dave        42.7
Janick      65.4
Related