Main index

Introducing UNIX and Linux


Introduction to shells

Overview
Why do we need a shell?
Shell syntax
      Types of shell command
      Simple commands
      Pipelines
      Grouping commands
      Exit status
      List commands
Arithmetic
      Operators and functions
Making decisions
      The 'test' statement
            Operators used by 'test'
      The 'if' statement
Loops
      'For' loops
      'While' and 'until' loops
Searching for files
      Arguments to 'find'
Formatted output
      Arguments to 'printf'
Passing information to scripts
      Scripts with arguments
      Parameter expansion
Summary
Exercises

Arithmetic

The shell itself does contain some rudimentary facilities to do arithmetic, which we shall discuss later. However, it is not itself designed for doing such calculations, unlike most high-level languages. It is recognised, however, that non-trivial arithmetic will be required by some shell programmers. The solution adopted is to introduce a utility known as bc ('basic calculator'), which is a sophisticated calculator. Use of this utility deserves a chapter in its own right, and we shall merely touch on the possibilities that bc offers. The characteristics of bc include

  • arbitrary precision arithmetic,
  • a complete programming language including for and while loops and variables, and
  • ability to perform arithmetic in bases other than 10.

We omit here the complex structures in bc and concentrate on using bc to perform simple calculations in decimal.

By default, bc takes input from standard input; commands are one per line or separated by semicolons. Each command to bc is either an expression, which it evaluates, or a statement that affects the subsequent output. As a short example, consider the following dialogue:

bc
1+2
3
100/7
14
scale=5
100/7
14.28571
sqrt(2)
1.41421

Most of this dialogue is self-explanatory; scale=5 indicates that subsequent calculations should be displayed correct to 5 decimal places, and sqrt is a predefined function that calculates the square root of its argument. To use a function in bc, type the name of the function followed by its argument enclosed in parentheses. Thus to evaluate 'log base e of 10' the expression would be l(10) (lower-case 'ell').

If the 'scale' is set to 0, no calculations are performed on digits after the decimal point, and integer arithmetic is performed. In this case the operator % will yield integer remainder so that 11 % 3 would yield 2. Some of the operators require bc to be called with option -l ('library'). Trigonometric functions assume you are working with radians (and not degrees), and the exponential function e raises e (the base of natural logarithms, 2.718...) to the power of its argument.

In bc you can use parentheses to group parts of an expression together, so the expression

10 * (3 + 4)

would evaluate to 70. You can use as many parenthesised expressions as you like, provided you ensure that each opening parenthesis is matched by a closing one - i.e. the usual conventions in a programming language apply. Note that multiplication and division take precedence over addition and subtraction, so that

1 + 3 * 4

is equivalent to

1 + (3 * 4)

and not to

(1 + 3) * 4

If in doubt about precedence, use parentheses

Worked example

Use bc to find the number of seconds in a day.
Solution: The calculation we require is 24 x 60 x 60, and the dialogue that would follow is:

bc
24 * 60 * 60
86400

ctrl-D

Since bc takes input from standard input, to leave bc you type ctrl-D on a line of its own. We can also pipe expressions into bc, and

echo "1 + 2" | bc

would be a valid way of using bc, since the pipe ensures that the standard output of echo becomes the standard input to bc.

Worked example

Write a script to read in two numbers and display their product.
Solution: Use read to input the numbers, and then construct the expression that represents their product using the * operator in bc. This expression can then be passed to the standard input of bc using echo.

echo Input two numbers:    # Prompt the user ...
read N1 N2                 # read in two numbers ...
echo "$N1 * $N2" | bc      # pass their product to bc

Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck