Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting | ||
---|---|---|
Prev | Chapter 4. Introduction to Variables and Parameters | Next |
variables visible only within a code block or function (see also local variables in functions)
variables that affect the behavior of the shell and user interface
In a more general context, each process has an "environment", that is, a group of variables that hold information that the process may reference. In this sense, the shell behaves like any other process. Every time a shell starts, it creates shell variables that correspond to its own environmental variables. Updating or adding new environmental variables causes the shell to update its environment, and all the shell's child processes (the commands it executes) inherit this environment. |
The space allotted to the environment is limited. Creating too many environmental variables or ones that use up excessive space may cause problems.
(Thank you, S. C. for the clarification, and for providing the above example.) |
If a script sets environmental variables, they need to be "exported", that is, reported to the environment local to the script. This is the function of the export command.
A script can export variables only to child processes, that is, only to commands or processes which that particular script initiates. A script invoked from the command line cannot export variables back to the command line environment. Child processes cannot export variables back to the parent processes that spawned them. |
---
arguments passed to the script from the command line - $0, $1, $2, $3... $0 is the name of the script itself, $1 is the first argument, $2 the second, $3 the third, and so forth. [1] After $9, the arguments must be enclosed in brackets, for example, ${10}, ${11}, ${12}.
The special variables $* and $@ denote all the positional parameters.
Example 4-5. Positional Parameters
1 #!/bin/bash 2 3 # Call this script with at least 10 parameters, for example 4 # ./scriptname 1 2 3 4 5 6 7 8 9 10 5 MINPARAMS=10 6 7 echo 8 9 echo "The name of this script is \"$0\"." 10 # Adds ./ for current directory 11 echo "The name of this script is \"`basename $0`\"." 12 # Strips out path name info (see 'basename') 13 14 echo 15 16 if [ -n "$1" ] # Tested variable is quoted. 17 then 18 echo "Parameter #1 is $1" # Need quotes to escape # 19 fi 20 21 if [ -n "$2" ] 22 then 23 echo "Parameter #2 is $2" 24 fi 25 26 if [ -n "$3" ] 27 then 28 echo "Parameter #3 is $3" 29 fi 30 31 # ... 32 33 34 if [ -n "${10}" ] # Parameters > $9 must be enclosed in {brackets}. 35 then 36 echo "Parameter #10 is ${10}" 37 fi 38 39 echo "-----------------------------------" 40 echo "All the command-line parameters are: "$*"" 41 42 if [ $# -lt "$MINPARAMS" ] 43 then 44 echo 45 echo "Give me at least $MINPARAMS command-line arguments!" 46 fi 47 48 echo 49 50 exit 0 |
The bracket notation for positional parameters leads to a fairly simple way of referencing the last argument passed to a script on the command line. This also requires indirect referencing.
1 args=$# # Number of args passed. 2 lastarg=${!args} # Note that lastarg=${!$#} doesn't work. |
Some scripts can perform different operations, depending on which name they are invoked with. For this to work, the script needs to check $0, the name it was invoked by. There must also exist symbolic links to all the alternate names of the script.
If a script expects a command line parameter but is invoked without one, this may cause a null variable assignment, generally an undesirable result. One way to prevent this is to append an extra character to both sides of the assignment statement using the expected positional parameter. |
1 variable1_=$1_ 2 # This will prevent an error, even if positional parameter is absent. 3 4 critical_argument01=$variable1_ 5 6 # The extra character can be stripped off later, if desired, like so. 7 variable1=${variable1_/_/} # Side effects only if $variable1_ begins with "_". 8 # This uses one of the parameter substitution templates discussed in Chapter 9. 9 # Leaving out the replacement pattern results in a deletion. 10 11 # A more straightforward way of dealing with this is 12 #+ to simply test whether expected positional parameters have been passed. 13 if [ -z $1 ] 14 then 15 exit $POS_PARAMS_MISSING 16 fi |
---
Example 4-6. wh, whois domain name lookup
1 #!/bin/bash 2 3 # Does a 'whois domain-name' lookup on any of 3 alternate servers: 4 # ripe.net, cw.net, radb.net 5 6 # Place this script, named 'wh' in /usr/local/bin 7 8 # Requires symbolic links: 9 # ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe 10 # ln -s /usr/local/bin/wh /usr/local/bin/wh-cw 11 # ln -s /usr/local/bin/wh /usr/local/bin/wh-radb 12 13 14 if [ -z "$1" ] 15 then 16 echo "Usage: `basename $0` [domain-name]" 17 exit 65 18 fi 19 20 case `basename $0` in 21 # Checks script name and calls proper server 22 "wh" ) whois $1@whois.ripe.net;; 23 "wh-ripe") whois $1@whois.ripe.net;; 24 "wh-radb") whois $1@whois.radb.net;; 25 "wh-cw" ) whois $1@whois.cw.net;; 26 * ) echo "Usage: `basename $0` [domain-name]";; 27 esac 28 29 exit 0 |
---
The shift command reassigns the positional parameters, in effect shifting them to the left one notch.
$1 <--- $2, $2 <--- $3, $3 <--- $4, etc.
The old $1 disappears, but $0 (the script name) does not change. If you use a large number of positional parameters to a script, shift lets you access those past 10, although {bracket} notation also permits this.
Example 4-7. Using shift
1 #!/bin/bash 2 # Using 'shift' to step through all the positional parameters. 3 4 # Name this script something like shft, 5 #+ and invoke it with some parameters, for example 6 # ./shft a b c def 23 skidoo 7 8 until [ -z "$1" ] # Until all parameters used up... 9 do 10 echo -n "$1 " 11 shift 12 done 13 14 echo # Extra line feed. 15 16 exit 0 |
The shift command also works on parameters passed to a function. See Example 34-11. |
[1] | The process calling the script sets the $0 parameter. By convention, this parameter is the name of the script. See the manpage for execv. |