LUX 211 - Shell Programming

Lesson 4: Chapter 8, The Bourne Again Shell, part 2

Objectives:

This lesson concludes the lessons on chapter 8. Objectives important to this lesson:

  1. Functions
  2. Features and options
  3. Command line
Concepts:
Chapter 8

Last time we stopped at page 346. Let's take a look at functions. The text explains the economy of functions on that page. A function can be defined and called from the command line, defined and called in a script, or it can be defined and loaded from a separate file (e.g. ~/.bash_profile), making it available to any script that might need to call it.

To use a function, it needs to be loaded into RAM. This is true for any command. Unlike standard commands, however, functions can remain available in RAM after they are used. This introduces one value of functions: they can be loaded into RAM from a startup file before you have need of them, which speeds up the time it takes to execute them when they are called. The downside is that you can put so many functions in RAM that it affects how much memory is left for your actual commands and scripts. You only want to preload functions you actually intend to use a lot.

Functions can be removed from memory with the unset command that we talked about last time. The text informs us about a potential problem, however. We can have a function with the same name as a variable. (Let's not do that, okay?) The point: if we have a function and a variable with the same name, calling unset with that name as its argument will remove the variable from memory first, and calling unset with that name once again would remove the function from memory.

This is a basic structure for writing/defining a function:

function_name ()
{
command line 1
command line 2
}

In this generic structure, you should see that a function must have a name, it must have parentheses that may (or may not) be empty, and it must contain one or more command lines to execute, which are contained by a set of curly braces. Although you are allowed to put the entire function on one line, if you do that, the last line of the set of commands must end with a semi-colon to separate it from the closing curly brace. The closing curly brace is meant to be seen as a separate instruction, closing the body of the function, which is why you often see it on a line by itself.

The formal statement of the structure and commands in a function may be called the function definition. You can create a function definition on a command line, but you will usually do it in a script. If your commands require that the function terminate under some conditions, you should test for those conditions as needed, and if they exist, end the running function with the break command.

  • local - On page 347, the author demonstrates the use of the local modifier. If a variable in a function is declared to be local, that variable is available only to the function itself and its children. If you do not declare the variable as being local, the variable is available to the shell that called the function.
  • export - If you have placed a function in RAM, you can make it available to other processes in the environment by exporting it. Note the procedure on page 347: you must use the -f option to export a function. The text does not present an example, so here is one for you:
    Example: export -f functionname
  • startup script - Page 348 gives us an example of a function in a startup script. Essentially, you just define the function, but you place it in a script that runs when you log in to the system.
  • arguments - The text explains that we can pass arguments to a function, the same way that we can pass them to a script. We can pass up to nine arguments to a function, then reference their values in the function's code as $1 for the first argument, $2 for the second argument, and so on through $9. If your logic has to know how many arguments were on the command line, that total is accessible as $#.

On page 349, the text begins a section that is better used for reference than for lesson material. We should take a look at some of the highlights:

  • shell options -  When starting the shell, you can engage any of the options shown on page 349, such as ignoring four (/etc/profile, ~/.bash_profile, ~/.bash_login, and ~/.profile) or just one (~/.bachrc) startup files, or all five of them. This can be a cleaner way to run a troubleshooting session, assuming you do not want your usual customized environment engaged.
  • shopt - Pages 350 through 353 list shell features that can be turned on or off with the shopt (shell options) command. So are they options or commands? Who cares, really, if you know how to toggle the ones you want to use. Browse through the list of commands to see if anything seems useful to you.
  • math expressions - On page 359, the text reveals a secret to getting the shell to do math. When you want to get the answer to a math problem, put the problem inside double parentheses, and precede them with a dollar sign like this:
    answer1=$((12+13+24+66))
    The shell will read the numbers, add them up, and assign the answer to the variable.

    In the second example on that page, the author has placed a variable and a number inside the double set of parentheses, and demonstrated that we do not have to put a dollar sign by the variable's name to use it in this kind of math expression. The user's current age is stored in a variable called age, and it is used in an echo statement:
    echo "Wow, in $((100-age)) years, you'll be 100!"
    This is interesting in that the shell knows to use the value of any variable inside the double quotation marks. You should make sure that you only put numbers, variables that hold numbers, and math operators inside the double parentheses. The shell assumes that all numbers in an expression like this will be integers, even those held in variables. You are allowed to use dollar signs with the variable names, but in they are not required in a math expression.

    In the third example on page 359, the author points out two things. First, that the asterisks he is using for multiplication are recognized as such because they are inside the double parentheses. Second, he points out that math expression evaluation works whether the math expression is included inside a string or not. (His previous example was in a string that was being echoed.)
  • let - To make this totally confusing, the author tells us another way to do math. On page 360, we see that the shell will understand that math expressions are supposed to follow the let command. Examples:
    let a=5+3
    let b=7+2
    let c=a+b d=c/4