Passing bash expression to AWK for floating point arithmetic

I tried to do floating point arithmetic in bash but since floats are not supported, tried to get a solution using AWK. Below is the problem I am facing:

I see that this works great 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 the expression " and calculate the value corresponding to 4 decimal places, so I tried to enter a code with the same expression (-225.2 * 7 + 30 * 6) / 17 + (19 ^ 2) / 9) and its providing incorrect values ​​(the variable i guess is passed as a 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 the second + in this example expression, which I can remove using sed or similar methods (with a space, I get a syntax error in awk when passing a variable from bash).

Any help is greatly appreciated. thanks in advance

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

+3


source to share


4 answers


You cannot 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 pronounce your expression correctly, 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

      

+3


source


I recommend and believe in the answer to James Brown. But if you need something here and now without 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 use eval

, so if this is not expanded, when you know you can trust the input (for example, because it comes from a managed process, not an actual user), you will need to execute some (and even then, probably deal with odd or downright misleading error messages if the input is not a valid Awk expression).



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

      

Pay attention also to the design to avoid the useless echo

. Redirecting input from /dev/null

and putting your code in a block END

(or BEGIN

) is the standard technique for running an arbitrary part of an Awk script without the need for input.

+1


source


First, I don't see anything wrong with the team, it should work. Please try again with the exact commands and provide the exact information if the problem persists.

However, if all you want is outputting, you can do it directly with printf

.

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

      

EDIT:

If you need to format the result after doing some calculations, you can alternatively use bc

. ( awk

should 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

      

0


source


Is this what you are looking for?

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

      

-1


source







All Articles