Although the original Bourne shell has no built-in arithmetic handlers, arithmetic can still be done using command substitution along with the expr command. Here's an example: var3=`expr var1 + var2` This adds the values contained in var1 and var2 together and then stores the result in var3. Note that the arguments and the operator must be separated by whitespace. expr var1+var2 will not have the intended result. The expr command can do only very simple mathit can handle only integer arithmetic. Entering floating-point numbers will cause an error. Changing the order of operations with parentheses is not supported. Division that does not return an integer value will have the decimal portion dropped. For example, 5 / 2 is 2 as far as expr is concerned. If you want to retrieve the remainder of a division, you can use the modulus operator (%). For example, expr 5 % 2 will return 1 (5 / 2 = 4 remainder 1). Characters that have special meaning to the shell must be escaped. For example, expr 2 * 2 will not work because the shell interprets the * as a wildcard operator. For the operation to work, the multiplication operator (*) must be escaped like this: expr 2 \* 2. This protects it from the shell's interpreting it as having a special meaning. expr can also evaluate true/false expressions. If the expression is true, expr returns a 1. If the expression is false, expr returns 0. Here's an example: expr 2 + 2 = 4 + 1 This command returns 0 (the equation is false). This next example returns 1 (the equation is true): expr 2 + 2 = 3 + 1 != will reverse the sense of the equationit means "is not equal to." So, for example, the equation expr 5 != 3 will return 1 (true). expr can, of course, also evaluate less than/greater than comparisons. Once again, because the < and > characters have special meaning to the shell, they must be escaped when used with expr to make sure they retain their mathematical meanings. Comparisons are true/false evaluations just like the "equal to" operator. If the expression is true, expr returns 1. If the expression is false, expr returns 0. For example, expr 5 \> 4 returns 1 (the expression is true). Greater than or equal to (\>=) and less than or equal to (\<=) evaluations are also supported. expr is not limited to comparing numbersit can also compare strings. For example, expr "The quick brown fox jumps over the lazy dog" = "The quick brown fox jumps over the lazy dg" will evaluate to 0 (the expression is false unless the strings are exactly equal). Although expr is great for simple shell scripting, as mentioned previously, its capabilities are rather limited. If you need to do floating-point math, work with complex expressions that change the order of operations, and so on, you can use a command called bc, which is a programming language in itself designed for working more flexibly with math than can be done in the basic shell language. It's possible to embed expressions into your shell program and feed them to bc. The program in Listing 10.6 uses bc to compute both the circumference and the area of a circle. Note that the argument to bc is l, the lowercase letter L. This option defines the standard math library for bc. Listing 10.6. Using bc to Compute the Circumference and Area of a Circle
Most of the concepts used in this program have already been explained, in the sections "Variables" and "Interacting with the User." Therefore, rather than go through the program line by line, we'll just cover the concepts that are new and/or important to the operation of the program:
This is only a very simple use of bc. bc is quite powerful and can do much more than the examples you've seen here. See the man page for bc if you are interested in learning more about its capabilities, both inside shell scripts and in standalone programs. |