Project 87. Scripting Tips"How do I write a function that returns an array of values?" This project presents several tips that you might find useful when writing Bash shell scripts. It shows you how to declare variables and arrays, perform integer arithmetic, test if a value is numeric, return values from functions, and implement variable variables. Tip
Declare Your VariablesThis tip has nothing to do with the red channel at Customs. Declaring a variable is a way of telling Bash more about how you are going to use the variable. To declare a variable, use the Bash built-in command declare, followed by a type and variable name. Variable types include integer and array, both of which are described at greater length in this project. In the next example, we declare the variable count to be an integer variable and perform some simple integer arithmetic, setting and incrementing count. First, by way of comparison, we try the sequence with an undeclared variable, which is taken by Bash to be a general-purpose string variable. $ s=1 $ s=s+1 $ echo $s s+1 $ declare -i count=1 $ count=count+1 $ echo $count 2 You may also declare variables read-only and export them as environment variables. Bash lets you declare a variable to be an array. An array variable holds many values, each accessed by its ordinal number (index). The following examples illustrate this. Declare an array, and initialize it by specifying the option -a and listing the values you wish to assign within parentheses, separated by spaces. Enclose in double quotes any values that contain spaces. $ declare -a products $ products=(iBook iMac PowerBook PowerMac ¬ "iPod shuffle" AirPort) To retrieve a particular value, expand the array variable name, employing the syntax ${array-variable-name[index]} To display the first value, which has an index of 0, and the fifth value, which has an index of 4, type $ echo ${products[0]} iBook $ echo ${products[4]} iPod shuffle Display all values by giving an index of star. $ echo ${products[*]} iBook iMac PowerBook PowerMac iPod shuffle AirPort To display the number of values in the array, type $ echo ${#products[*]} 6 To display the length, in characters, of the second value in the array, type $ echo ${#products[1]} 4 To create a list of all values, use a for loop to list all values one at a time. $ for p in "${products[@]}"; do echo $p; done iBook ... iPod shuffle AirPort $ Enclosing the expansion in double quotes, and using an index @ (instead of *), ensures that each value is expanded to preserve spaces; without this, iPod shuffle expands into two values. Learn More
Use Integer Arithmetic ExpressionsBash provides a special syntax for integer arithmetic expressions and comparisons, in which variables are automatically expanded and assumed to have the type integer. Expressions are enclosed within $((...)), and conditions, within ((...)). Within the double parentheses, you may employ expressions very much like those of the C programming language. Tip
Here are a couple of examples. $ i=7; j=35 $ echo $((i+j)) 42 $ if (((i*j) == 245)); then echo "yes"; fi yes As a trivial example, we might offer a thousand greetings in the following manner. $ a=1000; while ((a!=0)); do echo -n "*hello*"; ¬ ((a--)); done Test for a Numeric ValueHere's a handy tip to determine whether a value is numeric. The line beginning with read generates a prompt, (Give a number) and assigns whatever you type to variable num. The line beginning with if tests num to see whether it's numeric. $ read -p "Give a number: " num Give a number: i23 $ if [ "${num//[0-9]/}" ]; then echo "Not numeric"; fi Not numeric $ read -p "Give a number: " num Give a number: 123 $ if [ "${num//[0-9]/}" ]; then echo "Not numeric"; fi Project 76 explains the parameter extension techniques we used in this trick. Return Arbitrary ValuesA Bash shell script or function may return an exit condition of 0 to 255, which is available in the shell special variable $?. To return an arbitrary value, we use the following trick, shown here applied to a Bash function. The function return-eg returns a string value, simply set to Janet, to illustrate the technique. The function echoes its return value, and the calling script captures that value by calling the function and enclosing it in $(...). This syntax tells Bash to execute the function and replace it with its own output; thus, we assign the return value to the variable name. $ cat return-eg return-eg () { # processing here result="Janet" echo $result } name=$(return-eg) echo $name $ ./return-eg Janet Learn More
If we combine the arbitrary-value trick with Bash array variables, we can write and call a function that returns many values. $ cat return-eg return-eg () { # processing here result="Janet Sophie" echo $result } declare -a guests guests=($(return-eg)) for ((i=0; i<${#guests[*]}; i++)); do echo "guest $((i+1)) ${guests[i]}" done $ ./return-eg guest 1 Janet guest 2 Sophie Variable VariablesLanguages such as PHP implement variable variables. If you know what they are and would like to simulate their functionality in Bash, this trick is for you. Here's an example in which we echo the value of the variable detailsJanet. $ echo $detailsJanet Name: Janet Forbes, Country: England Now we try the same exercise, except that the Janet part of the variable is itself held in a variable and, naturally, could be anything. $ read -p "Give name: " name Give name: Janet $ eval "echo \$details$name" Name: Janet Forbes, Country: England The built-in eval command tells Bash to expand the quoted command sequence and then to execute the expanded text as though it were the original command. The net effect is to expand the line twice before it's executed. After eval is executed, the command sequence in the example above becomes echo $detailsJanet Then this command is executed in the normal manner. If you were to give a different name, such as Sophie, in response to the Give name: prompt, the final statement would evaluate to echo $detailsSophie |