awk - round to 2 decimals
Andrew Henderson
I am computing the percentages of every item in a column of a file using the following awk command:
awk '{a[NR]=$2;x+=(b[NR]=$2);c[NR]=$1}END{while(++i<=NR)print c[i]"\t"a[i]"\t"100*b[i]/x"%"}' file.txt > out_file.txtfile.txt
N 38668442
V 14008521
ADJ 16112215 out_file.txt
N 38668442 56,213%
V 14008521 20,3644%
ADJ 16112215 23,4226%However, I would like the percentages in the out_file.txt to be rounded to 2 decimals.
desired out_file.txt
N 38668442 56,21%
V 14008521 20,37%
ADJ 16112215 23,42%Referring to this post:
I tried to integrate printf "%s,%d,%0.2f%\n into my code which raises an argument error even by decreasing the arguments and limit the expression to %0.2f%\n.
awk '{a[NR]=$2;x+=(b[NR]=$2);c[NR]=$1}END{while(++i<=NR)printf "%s,%d,%0.2f%\n",c[i]"\t"a[i]"\t"100*b[i]/x"%"}' file.txt > out_file.txtAlso bc did not work out. Why does it not produce the desired output? In my opinion, it should work as I found the expression printf "%0.2f\n" in several posts concerning the same issue. Do I miss something trivial?
I greatly appreciate any help or suggestions!
2 Answers
You are misunderstanding the syntax of the printf command (which closely follows that of the underlying C function: see for example man 3 printf for full documentation).
printf takes a format string consisting of a sequence of format specifiers and other literal characters, followed by as many comma-separated arguments as necessary to fill the given format. In your command
printf "%s,%d,%0.2f%\n",c[i]"\t"a[i]"\t"100*b[i]/x"%"you are telling it to expect 3 values (a %s, a %d, and a %0.2f) but are giving it a single, concatenated, string argument c[i]"\t"a[i]"\t"100*b[i]/x"%". Hence it will run out of arguments during the assignment.
What you presumably intended is
printf "%s\t%d\t%0.2f%%\n", c[i], a[i], 100*b[i]/x(the tabs go inside the format string; the %% corresponds to a literal % i.e. prevents % from being interpreted as the start of another format specifier).
You can also use a function like this which fixes the annoying fact that awk rounds 0.5, etc. down.
function round(number, nDecimals, coef, i)
{ coef = 1 for (i = 1; i <= nDecimals; ++i) { coef *= 10 } number *= coef number >= 0 ? number += 0.5 : number -= 0.5 number = int(number) number /= coef return number
}Then you can write this to print the input rounded to two decimals:
print round($0, 2)