Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic precision in awk printf using shell variable

Tags:

bash

awk

I think this is simple, but it's not working for me. This is what I have.

float=$(awk -v res="$result" 'BEGIN {printf "%.2f", res / 1000}')

I want to use a variable to set the decimal value for %.2f but awk will have none of it. This is what I need.

var=2
float=$(awk -v res="$result" 'BEGIN {printf "%.${var}f", res / 1000}')

I hope someone can show me the error of my ways.

like image 901
WesZ Avatar asked Oct 23 '25 15:10

WesZ


2 Answers

awk's printf, like C's, lets you use a * instead of a hardcoded width or precision number. The value is instead taken from the next argument to the function. So instead of messing with shell substitution into the awk script, you can just pass the precision as another variable:

$ result=2050
$ prec=2
$ awk -v res="$result" -v p="$prec" 'BEGIN { printf "%.*f\n", p, res/1000 }'
2.05

However, if you're going to do a lot with floating point numbers, I'd suggest moving away from bash to another shell like zsh or ksh that supports floating-point math natively, or to a non-shell scripting language (perl, tcl, ruby, etc.). Tends to be more efficient than having to run external programs to do basic things like division.

like image 50
Shawn Avatar answered Oct 25 '25 06:10

Shawn


I suggest:

result="123456"
var=2            # decimal places

awk -v res="$result" -v dp="$var" 'BEGIN {printf "%." dp "f", res / 1000}'

or

awk -v res="$result" -v CONVFMT="%.${var}f" 'BEGIN {printf res / 1000}'

Output:

123.46

From man awk:

CONVFMT: The conversion format for numbers, "%.6g", by default.

like image 23
Cyrus Avatar answered Oct 25 '25 04:10

Cyrus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!