PRD
PRD

Reputation: 88

passing bash expression to AWK for floating point arithmetic

I was trying to do floating point arithmetic in bash, but as floats are not supported, was trying to get the solution using AWK. Below is the issue i am facing:

I see this working fine for me:

code

echo - | awk '{printf("%04.4f \n", (-225.2*7+30*6)/17 + (19^2)/9) }'

output

-42.0301

But my motive is to "read an expression" and compute value correct to 4 decimals, so tried below code inputting same expression (-225.2*7+30*6)/17 + (19^2)/9) and its giving incorrect values(i guess variable is passed as string to awk):

code

read inpt 
echo - | awk -v input=$inpt '{printf("%04.4f \n", input) }'

output

0.0000

Note: Please ignore the space around second + in this example expression, that i can remove using sed or similar methods(with space i get syntactical error in awk while passing variable from bash).

Any help is highly appreciated. Thanks in advance

PS: the bash version in my case is "bash-4.2". I guess its the version of bash preventing me using from many other options.

Upvotes: 3

Views: 3534

Answers (4)

Lalit Somnathe
Lalit Somnathe

Reputation: 111

Is this what you are looking for ?

 echo "25 50"| awk '{print $2,"/",$1}' | bc

Upvotes: -1

tripleee
tripleee

Reputation: 189317

I recommend and have upvoted James Brown's answer. But if you need something here and now with no external dependencies, you can simply interpolate the input into the script.

awk "END { printf("%04.4f\n", $input) }" </dev/null

This is functionally equivalent to using eval so if this isn't deployed where you know you can trust the input (e.g. because it comes from a controlled process, not an actual user) you will need to perform some sort of sanitization (and even then probably cope with odd or outright misleading error messages if the input isn't a well-formed Awk expression).

read -p "Input an Awk expression: " input
case $input in
  *[!-+/*()^%0-9]*)
    echo "$0: invalid input" >&2
    exit 1;;
esac
awk ...

Notice also the construct to avoid the basically useless echo. Redirecting input from /dev/null and putting your code in the END (or BEGIN) block is a standard technique for running an arbitrary piece of Awk script without requiring any input.

Upvotes: 1

James Brown
James Brown

Reputation: 37394

You can't evaluate data in a variable in awk out of the box. In this case you need to write an arithmetic evaluator or use a pre-existing one, like https://github.com/radare/radare2-bindings/blob/master/awk/calc.awk . Once you fix that missing parenthesis and quote your expression properly, you can:

$ echo "((-225.2*7+30*6)/17 + (19^2)/9)" | awk -f calc.awk
((-225.2*7+30*6)/17 + (19^2)/9) =        -42.0301

Upvotes: 4

Anubis
Anubis

Reputation: 7425

First, I don't see anything wrong in the command, it should work. Please try again the exact commands posted and provide exact details if the issue persists.

However, if all you need is formating the output, you can do it directly with printf.

$ read input
12.34
$ printf '%4.4f' $input
12.3400

EDIT:

If you need to format the output after performing some calculation, then you can alternatively use bc. (awk should still work)

$ echo "scale=4; (-225.2*7+30*6)/17+(19^2)/9" | bc
-42.0300

You can use variables in the expression as usual,

$ read inpt
1234
$ echo "scale=4; $inpt * 0.01" | bc
12.34

Upvotes: 0

Related Questions