enriched
enriched

Reputation: 400

Bash function to do awk math (floating point)

I want to create a simple bash function that will evaluate the math that I pass it using awk. eg:

awkmath()
{
  echo "$1 $3" | awk '{ print($1 "'$2'" $2) }'
}

awkmath '2' '*' '3'  #Prints 6

So far I can't get this to work though. Instead of getting "6" I get "2*3". I know there are other ways to do this. But I'm interested in seeing if someone can make this work. It seems like a simple thing, but the bash interpreting gets a little nuts.

Upvotes: 0

Views: 283

Answers (2)

glenn jackman
glenn jackman

Reputation: 246744

I'd use bc instead of awk: your math expression can be arbitrarily complex

math() {
  local out=$(bc -l <<< "$*")
  if [[ -z $out ]]; then
    return 1
  else
    echo "$out"
  fi
}

math '(2+3)' \* '(5-sqrt(9))'

You do have the pain of protecting characters that are special to the shell

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 203209

awkmath()
{
  echo "$1 $3" | awk '{ print $1 '"$2"' $2 }'
}
$ awkmath '2' '*' '3'
6

This uses the string delimiters (") in the shell to avoid globbing and word splitting before constructing the awk command:

'{print $1 '"$2"' $2}' -> '{print 2 '"*"' 3}' -> '{print 2 * 3}'

while what you had originally leaves * inside string delimiters after constructing the awk coommand:

'{print $1 "'$2'" $2}' -> '{print 2 "'*'" 3}' -> '{print 2 "*" 3}'

and in fact you'd be lucky in that 2nd case if the * wasn't expanded into a list of file names in your current directory before the awk command was constructed.

Upvotes: 2

Related Questions