Shell scripting is an easy way to automate tasks on unix systems, but how to do some
real computing in plain shell? For fun the other day I was trying to figure out how
to calculate bouyancy of some primitive geometric shapes, and this is where the metric
system really shines. 1 cubic meter is 1000 liters, and 1 liter displaces approximately
1 kilogram at sea level (eureka!). So all I needed was a volume in cubic meters, but I
don't want to write a perl or python script. Let's use bash, because why not?
First, this script depends on bash for the read call, though other shells may
also support
read -s -n 1
We must define PI for the circular area formulas.
#!/bin/bash
PI="3.14159"
This function is used to catch any mistaked in the bc commands, first rule of being a
good programmer is to always check for errors when possible!
# an empty string from stdout is an error
bc_check_error() {
if [ "$1" = "" ]; then
exit -1
fi
}
NOTE: I did not bother to write an error checking function for diameter and length input,
that could be an exercise for another day, hopefully the bc_error_check() catches any
mistakes.
cylinder() {
echo ""
echo "volume of cylinder, enter diameter and length"
printf "diameter: "
read DIAMETER
printf "length: "
read LENGTH
We use the VOLUME variable to store the returned string from
bc.
scale=5
tells bc to use 5 decimal places of precision. This could be much higher if our PI
variable demanded greater precision. rad=($DIAMETER/2.0) creates a variable for
the radius, and finally the cylinder volume is V = ( PI r^2 ) * LENGTH. (PI * r^2) being
a circles area, multiply by length and there we have it. The semicolons are used
by bc to separate the 3 commands we strung together.
VOLUME=$(echo "scale=5; rad=($DIAMETER/2.0); $PI * (rad * rad) * $LENGTH" | bc)
bc_check_error "$VOLUME"
}
sphere() is not quite the same as cylinder, V =( 4/3 PI r^3 )
sphere() {
echo ""
echo "volume of sphere, enter diameter"
printf "diameter: "
read DIAMETER
VOLUME=$(echo "scale=5; rad=($DIAMETER/2.0); (4.0 / 3.0) * $PI * (rad * rad * rad)" | bc )
bc_check_error "$VOLUME"
}
Here we print the option menu, and call the requested function to store the result
in VOLUME. That's all folks! Below is the full script all together:
echo ""
echo "choose geometric shape:"
echo " 1. cylinder"
echo " 2. sphere"
read -s -n 1 SHAPE
if [ "$SHAPE" = "1" ]; then
cylinder
elif [ "$SHAPE" = "2" ]; then
sphere
else
echo "error: choose either 1 or 2"
exit -1
fi
echo "volume = $VOLUME"
So as you can see, even
bash or plain
sh is capable of complex computations
once you learn how
bc works. It may not be the fastest way to compute but it gets
the job done, and runs without requiring a heavy weight interpretter be installed.
#!/bin/bash
PI="3.14159"
# an empty string from stdout is an error
bc_check_error() {
if [ "$1" = "" ]; then
exit -1
fi
}
cylinder() {
echo ""
echo "volume of cylinder, enter diameter and length"
printf "diameter: "
read DIAMETER
printf "length: "
read LENGTH
VOLUME=$(echo "scale=5; rad=($DIAMETER/2.0); $PI * (rad * rad) * $LENGTH" | bc)
bc_check_error "$VOLUME"
}
sphere() {
echo ""
echo "volume of sphere, enter diameter"
printf "diameter: "
read DIAMETER
VOLUME=$(echo "scale=5; rad=($DIAMETER/2.0); (4.0 / 3.0) * $PI * (rad * rad * rad)" | bc )
bc_check_error "$VOLUME"
}
echo ""
echo "choose geometric shape:"
echo " 1. cylinder"
echo " 2. sphere"
read -s -n 1 SHAPE
if [ "$SHAPE" = "1" ]; then
cylinder
elif [ "$SHAPE" = "2" ]; then
sphere
else
echo "error: choose either 1 or 2"
exit -1
fi
echo "volume = $VOLUME"