Global and local variables
Suppose a process assigns a value to a variable. The value
cannot be passed to the parent process, but may be passed to child
processes. To illustrate this, consider a variable called
X , which we set to be the number 42 . Then
invoke a second copy of the shell using sh ; you will
get the usual prompt, but this prompt is from the new shell, not
from your login shell. The new shell is a child of your login
shell. Now check the value of X , and you will see it
is not assigned a value:
$ X=42
$ echo $X
42
$ sh
$ echo $X
(blank line)
$
The new value of X is not passed down to the child
process. We say that the value of X is
local to the process that assigned it the value,
and no changes will be recognised by any child process. If you now
cause the child shell to finish by typing ctrl-D, you will
get the $ prompt again, this time from your login
shell. Now, if you examine the value of X again, you
will see that it is 42 , as that was the value assigned
to it in the login shell.
We can cause a variable instead to be global by
means of the command export , which means that its
value will be passed down to all the child processes, and their
children, and so on. Do the same as in the example above, but
immediately after setting X to 42 , type a
line export ing X :
$ export X
Worked example
Change your prompt from $ to enter
command:
Solution: The variable PS1 contains
the prompt; reset it and export its value:
$ PS1="enter command: "
enter command: export PS1
Another method for assigning a variable a value is by means of
the command read . Followed by one or more variable
names, this reads words from the standard input and assigns them to
the successive variables. The following script requests the name of
a user and sends them a greeting by mail:
echo "Whom do you wish to greet?"
read RECIPIENT
echo Hello | mailx -s Greeting $RECIPIENT
Generally you will read one variable at a time, but it is
possible to read several at once from a single line of input. In
this case you must be careful if the number of variables, and the
number of words on the input line, are different. If there are
fewer variables than words on the line, the initial variables will
be assigned one word each, and the final one the rest of the line;
if there are more variables than words on the line, the final
variables will be assigned the null string. If script testread has
the following contents:
read X Y Z
echo "X=$X Y=$Y Z=$Z"
then we might have the following:
$ sh testread
hello there chris
X=hello Y=there Z=chris
$ sh testread
hello
X=hello Y= Z=
$ sh testread
hello there chris jo and sam
X=hello Y=there Z=chris jo and sam
Worked example
Write a script to prompt the user for the name of a file and
then print the file on their terminal.
Solution: Use echo to prompt the
user, read to get a filename into a variable, and
cat to display the file:
echo Type in a filename
read FILENAME
cat $FILENAME
One use of read that is not apparent from the above
discussion is that it can be used to allow the user control over
the speed with which a shell script is executed. Try creating a
file (say cat2files ) containing the following:
echo Type in 2 file names
read FILE1 FILE2
cat $FILE1
echo Press Return to continue
read X
cat $FILE2
Now execute that script - it will print out the first file on
the screen, then pause for you to press Return before
displaying the second file. The second read assigns a
value to the variable X (which is not actually used
for anything else), but waits for you to type in something before
moving on to the next line.
Suppose file myprogram contains
echo The emperor is $MY_NAME
and you wish to run the commands in the file with
MY_NAME set to a value. You could set
MY_NAME , then export it, then run the
file, so:
$ MY_NAME="Julius Caesar"
$ export MY_NAME
$ sh myprogram
The emperor is Julius Caesar
There is a problem with this, namely that you have reset
MY_NAME in the current shell as well. You may not wish
to do this. You may wish to test myprogram with the
variable MY_NAME assigned a different value. This
would be especially important if you were writing a script that
used system-defined variables, such as TERM or
LOGNAME , where it would be confusing if you were to
reset them. You can use the following:
$ MY_NAME="Julius Caesar" sh
myprogram
The emperor is Julius Caesar
This does not affect the current value of MY_NAME ,
but has the same effect as inserting the single line
MY_NAME="Julius Caesar"
at the start of the file myprogram . An equivalent
effect can be achieved using the command env :
$ env MY_NAME="Julius Caesar" sh
myprogram
The emperor is Julius Caesar
|