0

i have values stored in variables var1=6 and var2=4, i am trying to divide them with a precision of 2 and store the result in a variable var,

var=`awk 'BEGIN {printf "%.2f\n", $var1/ $var2}'`

when i perform the above operation i get awk: cmd. line:1: fatal: division by zero attempted

can someone please point out what exactly i am missing here.

Thanks!

  • awk is really needed ? var=$((echo scale=2 ; echo $var1 / $var2 ) | bc) – Archemar Dec 21 '20 at 12:09
  • unfortunately yes, as i am running an automation script in shared environment which doesn't recognize bc, so when i try using the same command that u suggested it says bash: bc: command not found – SomeoneNew2Unix Dec 21 '20 at 12:11

3 Answers3

1

use -v var=value to pass variable to awk.

thus

awk -v var1="$var1" -v var2="$var2" 'BEGIN {printf "%.2f\n",var1/var2}'

give

1.50

and

var=$(awk -v var1="$var1" -v var2="$var2" 'BEGIN {printf "%.2f\n",var1/var2}') 

set value.

you need

  • -v var1="$var1" to turn bash's $var1 to awk's var1
  • use var1 in awk (no need for $, $var1 with var1=6 would be $6's value)
  • echo to provide input to awk (or else awk would hang waiting for input) (forget about BEGIN in awk)
Archemar
  • 31,554
1

Here, you can pass the contents of the $var1 and $var2 shell variables as arguments to your awk script, and access them in the script via the special ARGV array variable:

var=$(awk -- 'BEGIN {printf "%.2f", ARGV[1] / ARGV[2]}' "$var1" "$var")

Or you can export the var1 and var2 shell variables to the environment for awk to retrieve them via its ENVIRON array variable:

var=$(
  export var1 var2
  awk 'BEGIN {printf "%.2f", ENVIRON["var1"] / ENVIRON["var2"]}'
)

In the general case, it's often preferable to use ARGV/ENVIRON over -v or var=value arguments to pass arbitrary data as those latter ones mangle backslash characters (not really an issue here for numbers though).

Embedding the expansion of the shell variable in awk's code argument should be avoided as it amounts to a code injection vulnerability. Same for forgetting to quote parameter expansions in arguments to -v.

Note that if the shell is ksh93 or zsh, you don't need awk at all here:

printf -v var %.2f '1.*var1 / var2' # zsh
var=${ printf %.2f '1.*var1 / var2'; } # ksh93

(where the multiplication with 1. forces the evaluation to be done as floating point).

However note that you'd need to sanitise the contents of those variables or otherwise that would be another arbitrary code execution vulnerability if the contents of those variables weren't under your control.

0

Should you really want to use awk, which is questionable for such a simple script but would make sense for a more complex one, here are two ways to overcome the issue:

  1. just replace the simple quote by double quotes. The simple ones prevent the dollar expansion. That introduces other issues like the requirement for existing double quotes to be escaped and the same requirement if you want to use fields in awk).

    var=`awk "BEGIN {printf \"%.2f\n\", $var1/ $var2}"`
    
  2. pass the variables to awk the right way:

    var=$(awk -v var1="$var1" var2="$var2" 'BEGIN {printf("%`.2f\n",var1,var2)}')
    
jlliagre
  • 61,204
  • 1
    thank you, the explanation of single quotes and double quotes actually helped in understanding the dollar expansion using awk – SomeoneNew2Unix Dec 21 '20 at 12:25