Search code examples
bashshellmathbc

Correct usage of bc in a shell script?


I'm simply trying to multiplying some float variables using bc:

#!/bin/bash

a=2.77 | bc
b=2.0  | bc

for cc in $(seq 0. 0.001 0.02)
do
    c=${cc} | bc
    d=$((a * b * c)) | bc
    echo "$d" | bc
done

And this does not give me an output. I know it's a silly one but I've tried a number of combinations of bc (piping it in different places etc.) to no avail.

Any help would be greatly appreciated!


Solution

  • bc is a command-line utility, not some obscure part of shell syntax. The utility reads mathematical expressions from its standard input and prints values to its standard output. Since it is not part of the shell, it has no access to shell variables.

    The shell pipe operator (|) connects the standard output of one shell command to the standard input of another shell command. For example, you could send an expression to bc by using the echo utility on the left-hand side of a pipe:

    echo 2+2 | bc
    

    This will print 4, since there is no more here than meets the eye.

    So I suppose you wanted to do this:

    a=2.77
    b=2.0
    for c in $(seq 0. 0.001 0.02); do
      echo "$a * $b * $c" | bc
    done
    

    Note: The expansion of the shell variables is happening when the shell processes the argument to echo, as you could verify by leaving off the bc:

    a=2.77
    b=2.0
    for c in $(seq 0. 0.001 0.02); do
      echo -n "$a * $b * $c" =
      echo "$a * $b * $c" | bc
    done
    

    So bc just sees numbers.

    If you wanted to save the output of bc in a variable instead of sending it to standard output (i.e. the console), you could do so with normal command substitution syntax:

    a=2.77
    b=2.0
    for c in $(seq 0. 0.001 0.02); do
      d=$(echo "$a * $b * $c" | bc)
      echo "$d"
    done