7.6. Variables
There are two types of variables: local and environment. Some variables are created by the user and others are special shell variables.
7.6.1 Local Variables
Local variables are given values that are known only to the shell in which they are created. Variable names must begin with an alphabetic or underscore character. The remaining characters can be alphabetic, decimal digits 0 to 9, or an underscore character. Any other characters mark the termination of the variable name. When assigning a value, there can be no whitespace surrounding the equal sign. To set the variable to null, the equal sign is followed by a newline.
A dollar sign is used in front of a variable to extract the value stored there.
Setting Local Variables
See Example 7.18 for a demonstration on setting a local variable
Example 7.18.
1 $ round=world
$ echo $round
world
2 $ name="Peter Piper"
$ echo $name
Peter Piper
3 $ x=
$ echo $x
4 $ file.bak="$HOME/junk"
file.bak=/home/jody/ellie/junk: not found
EXPLANATION
The variable round is assigned the value world. When the shell encounters the dollar sign preceding a variable name, it performs variable substitution. The value of the variable is displayed. The variable name is assigned the value "Peter Piper". The quotes are needed to hide the whitespace so that the shell will not split the string into separate words when it parses the command line. The value of the variable is displayed. The variable x is not assigned a value. The shell will assign the null value. The null value, an empty string, is displayed. The period in the variable name is illegal. The only characters allowed in a variable name are numbers, letters, and the underscore. The shell tries to execute the string as a command.
The Scope of Local Variables
A local variable is known only to the shell in which it was created. It is not passed on to subshells. The double dollar sign variable is a special variable containing the PID of the current shell.
Example 7.19.
1 $ echo $$
1313
2 $ round=world
$ echo $round
world
3 $ sh # Start a subshell
4 $ echo $$
1326
5 $ echo $round
6 $ exit # Exits this shell, returns to parent shell
7 $ echo $$
1313
8 $ echo $round
world
EXPLANATION
The value of the double dollar sign variable evaluates to the PID of the current shell. The PID of this shell is 1313. The local variable round is assigned the string value world, and the value of the variable is displayed. A new Bourne shell is started. This is called a subshell, or child shell. The PID of this shell is 1326. The parent shell's PID is 1313. The variable round is not defined in this shell. A blank line is printed. The exit command terminates this shell and returns to the parent shell. (Ctrl-D will also exit this shell.) The parent shell returns. Its PID is displayed. The value of the variable round is displayed.
Setting Read-Only Variables
A read-only variable cannot be redefined or unset.
Example 7.20.
1 $ name=Tom
2 $ readonly name
$ echo $name
Tom
3 $ unset name
name: readonly
4 $ name=Joe
name: readonly
EXPLANATION
The local variable name is assigned the value Tom. The variable is made readonly. A read-only variable cannot be unset. A read-only variable cannot be redefined.
7.6.2 Environment Variables
Environment variables are available to the shell in which they are created and any subshells or processes spawned from that shell. By convention, environment variables are capitalized. Environment variables are variables that have been exported.
The shell in which a variable is created is called the parent shell. If a new shell is started from the parent shell, it is called the child shell. Some of the environment variables, such as HOME, LOGNAME, PATH, and SHELL, are set before you log on by the /bin/login program. Normally, environment variables are defined and stored in the .profile file in the user's home directory. See Table 7.3 for a list of environment variables.
Table 7.3. Bourne Shell Environment VariablesVariable | Value |
---|
PATH | The search path for commands. | HOME | Home directory; used by cd when no directory is specified. | IFS | Internal field separators, normally space, tab, and newline. | LOGNAME | The user's login name. | MAIL | If this parameter is set to the name of a mail file and the MAILPATH parameter is not set, the shell informs the user of the arrival of mail in the specified file. | MAILCHECK | This parameter specifies how often (in seconds) the shell will check for the arrival of mail in the files specified by the MAILPATH or MAIL parameters. The default value is 600 seconds (10 minutes). If set to zero, the shell will check before issuing each primary prompt. | MAILPATH | A colon-separated list of filenames. If this parameter is set, the shell informs the user of the arrival of mail in any of the specified files. Each filename can be followed by a percent sign and a message that will be printed when the modification time changes. The default message is You have mail. | PWD | Present working directory. | PS1 | Primary prompt string, which is a dollar sign by default. | PS2 | Secondary prompt string, which is a right angle bracket by default. | SHELL | When the shell is invoked, it scans the environment for this name. The shell gives default values to PATH, PS1, PS2, MAILCHECK, and IFS. HOME and MAIL are set by login. |
Setting Environment Variables
To set environment variables, the export command is used either after assigning a value or when the variable is set. (Do not use the dollar sign on a variable when exporting it.)
Example 7.21.
1 $ TERM=wyse
$ export TERM
2 $ NAME="John Smith"
$ export NAME
$ echo $NAME
John Smith
$ echo $$
319 # pid number for parent shell
4 $ sh # Start a subshell
5 $ echo $$
340 # pid number for new shell
6 $ echo $NAME
John Smith
7 $ NAME="April Jenner"
$ export NAME
$ echo $NAME
April Jenner
8 $ exit # Exit the subshell and go back to parent shell
9 $ echo $$
319 # pid number for parent shell
10 $ echo $NAME
John Smith
EXPLANATION
The TERM variable is assigned wyse. The variable is exported. Now, processes started from this shell will inherit the variable. The variable is defined and exported to make it available to subshells started from the shell. The value of this shell's PID is printed. A new Bourne shell is started. The new shell is called the child. The original shell is its parent. The PID of the new Bourne shell is stored in the $$ variable and its value is echoed. The variable, set in the parent shell, was exported to this new shell and is displayed. The variable is reset to April Jenner. It is exported to all subshells, but will not affect the parent shell. Exported values are not propagated upward to the parent shell. This Bourne child shell is exited. The PID of the parent is displayed again. The variable NAME contains its original value. Variables retain their values when exported from parent to child shell. The child cannot change the value of a variable for its parent.
7.6.3 Listing Set Variables
There are two built-in commands that print the value of a variable: set and env. The set command prints all variables, local and global. The env command prints just the global variables.
Example 7.22.
1 $ env (Partial list)
LOGNAME=ellie
TERMCAP=sun–cmd
USER=ellie
DISPLAY=:0.0
SHELL=/bin/sh
HOME=/home/jody/ellie
TERM=sun–cmd
LD_LIBRARY_PATH=/usr/local/OW3/lib
PWD=/home/jody/ellie/perl
2 $ set
DISPLAY=:0.0
FMHOME=/usr/local/Frame–2.1X
FONTPATH=/usr/local/OW3/lib/fonts
HELPPATH=/usr/local/OW3/lib/locale:/usr/local/OW3/lib/help
HOME=/home/jody/ellie
HZ=100
IFS=
LANG=C
LD_LIBRARY_PATH=/usr/local/OW3/lib
LOGNAME=ellie
MAILCHECK=600
MANPATH=/usr/local/OW3/share/man:/usr/local/OW3/man:/
usr/local/man:/usr/local/doctools/man:/usr/man
OPTIND=1
PATH=/home/jody/ellie:/usr/local/OW3/bin:/usr/ucb:/usr/local/
doctools/bin:/usr/bin:/usr/local:/usr/etc:/etc:/usr/spool/
news/bin:/home/jody/ellie/bin:/usr/lo
PS1=$
PS2=>
PWD=/home/jody/ellie/kshprog/joke
SHELL=/bin/sh
TERM=sun–cmd
TERMCAP=sun–cmd:te=\E[>4h:ti=\E[>4l:tc=sun:
USER=ellie
name=Tom
place="San Francisco"
EXPLANATION
The env command lists all environment (exported) variables. These variables are, by convention, named with all uppercase letters. They are passed from the process in which they are created to any of its child processes. The set command, without options, prints all set variables, local and exported (including variables set to null).
7.6.4 Unsetting Variables
Both local and environment variables can be unset by using the unset command, unless the variables are set as read-only.
Example 7.23.
unset name; unset TERM
EXPLANATION
The unset command removes the variable from the shell's memory.
7.6.5 Printing the Values of Variables: The echo Command
The echo command prints its arguments to standard output and is used primarily in Bourne and C shells. The Korn shell has a built-in print command. There are different versions of the echo command; for example, the Berkeley (BSD) echo is different from the System V echo. Unless you specify a full pathname, you will use the built-in version of the echo command. The built-in version will reflect the version of UNIX you are using. The System V echo allows the use of numerous escape sequences, whereas the BSD version does not. Table 7.4 lists the BSD echo option and escape sequences.
Example 7.24.
1 $ echo The username is $LOGNAME.
The username is ellie.
2 $ echo "\t\tHello there\c" # System V
Hello there$
3 $ echo -n "Hello there" # BSD
Hello there$
Table 7.4. BSD echo Option and System V Escape SequencesOption | Meaning |
---|
BSD | –n | Suppress newline at the end of a line of output | System V | \b | Backspace | \c | Print the line without a newline | \f | Form feed | \n | Newline | \r | Return | \t | Tab | \v | Vertical tab | \\ | Backslash |
EXPLANATION
The echo command prints its arguments to the screen. Variable substitution is performed by the shell before the echo command is executed. The System V version of the echo command supports escape sequences similar to those of the C programming language. The $ is the shell prompt. The –n option to the echo command indicates the BSD version of the echo command is being used. The line is printed without the newline. The escape sequences are not supported by this version of echo.
7.6.6 Variable Expansion Modifiers
Variables can be tested and modified by using special modifiers. The modifier provides a shortcut conditional test to check if a variable has been set, and then assigns a value to the variable based on the outcome of the test. See Table 7.5 for a list of Bourne shell variable modifiers.
Table 7.5. Bourne Shell Variable ModifiersModifier | Value |
---|
${variable:–word} | If variable is set and is non-null, substitute its value; otherwise, substitute word. | ${variable:=word} | If variable is set or is non-null, substitute its value; otherwise, set it to word. The value of variable is substituted permanently. Positional parameters may not be assigned in this way. | ${variable:+word} | If parameter is set and is non-null, substitute word; otherwise, substitute nothing. | ${variable:?word} | If variable is set and is non-null, substitute its value; otherwise, print word and exit from the shell. If word is omitted, the message parameter null or not set is printed. |
Using the colon with any of the modifiers (–, =, +, ?) checks whether the variable is not set or is null; without the colon, a variable set to null is considered to be set.
Example 7.25.
(Assigning temporary default values)
1 $ fruit=peach
2 $ echo ${fruit:–plum}
peach
3 $ echo ${newfruit:–apple}
apple
4 $ echo $newfruit
5 $ echo $EDITOR # More realistic example
6 $ echo ${EDITOR:-/bin/vi}
/bin/vi
7 $ echo $EDITOR
8 $ name=
$ echo ${name-Joe}
9 $ echo ${name:-Joe}
Joe
EXPLANATION
The variable fruit is assigned the value peach. The special modifier will check to see if the variable fruit has been set. If it has, the value is printed; if not, plum is substituted for fruit and its value is printed. The variable newfruit has not been set. The value apple will be temporarily substituted for newfruit. The setting was only temporary. The variable newfruit is not set. The environment variable EDITOR has not been set. The :– modifier substitutes EDITOR with /bin/vi. The EDITOR was never set. Nothing prints. The variable name is set to null. By not prefixing the modifier with a colon, the variable is considered to be set, even if to null, and the new value Joe is not assigned to name. The colon causes the modifier to check that a variable is either not set or is set to null. In either case, the value Joe will be substituted for name.
Example 7.26.
(Assigning permanent default values)
1 $ name=
2 $ echo ${name:=Patty}
Patty
3 $ echo $name
Patty
4 $ echo ${EDITOR:=/bin/vi}
/bin/vi
5 $ echo $EDITOR
/bin/vi
EXPLANATION
The variable name is assigned the value null. The special modifier := will check to see if the variable name has been set. If it has been set, it will not be changed; if it is either null or not set, it will be assigned the value to the right of the equal sign. Patty is assigned to name because the variable is set to null. The setting is permanent. The variable name still contains the value Patty. The value of the variable EDITOR is set to /bin/vi. The value of the variable EDITOR is displayed.
Example 7.27.
(Assigning temporary alternate values)
1 $ foo=grapes
2 $ echo ${foo:+pears}
pears
3 $ echo $foo
grapes
$
EXPLANATION
The variable foo has been assigned the value grapes. The special modifier :+ will check to see if the variable has been set. If it has been set, pears will temporarily be substituted for foo; if not, null is returned. The variable foo now has its original value.
Example 7.28.
(Creating error messages based on default values)
1 $ echo ${namex:?"namex is undefined"}
namex: namex is undefined
2 $ echo ${y?}
y: parameter null or not set
EXPLANATION
The :? modifier will check to see if the variable has been set. If not, the string to the right of the ? is printed to standard error, after the name of the variable. If in a script, the script exits. If a message is not provided after the ?, the shell sends a default message to standard error.
7.6.7 Positional Parameters
Normally, the special built-in variables, often called positional parameters, are used in shell scripts when passing arguments from the command line, or used in functions to hold the value of arguments passed to the function. See Table 7.6. The variables are called positional parameters because they are denoted by their position on the command line. The Bourne shell allows up to nine positional parameters. The name of the shell script is stored in the $0 variable. The positional parameters can be set and reset with the set command.
Example 7.29.
1 $ set tim bill ann fred
$ echo $* # Prints all the positional parameters.
tim bill ann fred
2 $ echo $1 # Prints the first positional parameter.
tim
3 $ echo $2 $3 # Prints the second and third positional parameters.
bill ann
4 $ echo $# # Prints the total number of positional parameters.
4
5 $ set a b c d e f g h i j k l m
$ echo $10 # Prints the first positional parameter followed by a zero.
a0
6 $ echo $*
a b c d e f g h i j k l m
7 $ set file1 file2 file3
$ echo \$$#
$3
8 $ eval echo \$$#
file3
Table 7.6. Bourne Shell Positional ParametersPositional Parameter | Meaning |
---|
$0 | References the name of the current shell script | $1–$9 | Denotes positional parameters 1 through 9 | $# | Evaluates to the number of positional parameters | $* | Evaluates to all the positional parameters | $@ | Means the same as $*, except when double quoted | "$*" | Evaluates to "$1 $2 $3" | "$@" | Evaluates to "$1" "$2" "$3" |
EXPLANATION
The set command assigns values to positional parameters. The $* special variable contains all of the parameters set. The value of the first positional parameter, tim, is displayed. The value of the second and third parameters, bill and ann, are displayed. The $# special variable contains the number of positional parameters currently set. The set command resets all of the positional parameters. The original set is destroyed. Positional parameters cannot be numbered beyond nine. The value of the first positional parameter is printed, followed by the number 0. The $* allows you to print all of the parameters, even past nine. The positional parameters are reset to file1, file2, and file3. The dollar sign is escaped; $# is the number of arguments. The echo command displays $3. The eval command parses the command line a second time before executing the command. The first time parsed, the shell substitutes \$$# with $3, and the second time, the shell substitutes the value of $3 with file3.
7.6.8 Other Special Variables
The shell has special variables consisting of a single character. The dollar sign preceding the character allows you to access the value stored in the variable. See Table 7.7.
Example 7.30.
1 $ echo The pid of this shell is $$
The pid of this shell is 4725
2 $ echo The options for this shell are $–
The options for this shell are s
3 $ grep dodo /etc/passwd
$ echo $?
1
4 $ sleep 25&
4736
$ echo $!
4736
Table 7.7. Bourne Shell Special VariablesVariable | Meaning |
---|
$ | The PID of the shell | – | The sh options currently set | ? | The exit value of last executed command | ! | The PID of the last job put in the background |
EXPLANATION
The $ variable holds the value of the PID for this process. The – variable lists all options for this interactive Bourne shell. The grep command searches for the string dodo in the /etc/passwd file. The ? variable holds the exit status of the last command executed. Because the value returned from grep is 1, grep is assumed to have failed in its search. An exit status of 0 indicates a successful exit. The ! variable holds the PID number of the last command placed in the background. The & appended to the sleep command sends the command to the background.
|