The previous examples have shown how to assign a simple string to a specified variable. There are two other circumstances under which you might want a value assigned to a variable: first, you may want to have a shell script take a value interactively from the keyboard, which you subsequently wish to store in a variable and, second, you may wish to execute a command and have the standard output from the command redirected into a variable instead of displayed to the screen. As you may have guessed, both of these types of variable assignment are available.
A shell script can take lines of characters from the standard input and assign them to one or more variables using the read command. In its simplest form, the read command is just used on its own, with no variables specified. In this case, the string read in from the standard input is assigned to the variable REPLY. If you make an executable shell script called readtest1 out of the text:
echo -n 'Enter some text: ' read echo The text was: $REPLY
and then run it, you will get a result like the following:
$ readtest1 Enter some text: THIS IS THE TEXT I ENTERED!! The text was: THIS IS THE TEXT I ENTERED!!
Normally, when echo is used, it will automatically add a newline character to the end of the line, so that any further output will begin on the next line. As the example shows, using the -n switch to echo causes echo to suppress the newline ontput so that any subsequent characters sent to the display will follow on, on the same line. In this case the text that follows on is the text you enter in response to the read command. As you can see, this allows you to give a prompt from within a shell script and take a response immediately after it, on the same line.
If you specify a variable name after a read command then the input line will be assigned to that variable instead of the variable REPLY.
A more interesting case is what happens when you specify more than one variable after the read command. Consider the shell script readtest2:
echo -n 'Enter some text: ' read one two restofline echo The first word was: $one echo The second word was: $two echo The rest of the line was: $restofline
When executed, this script will read a line of input as before. This time, however, the line will be split into separate words. The first word will be assigned to the first variable listed, the second word will be assigned to the second variable, the third word to the third variable, and so on, until you run out of either words or variables (or both).
If you run out of words and variables together, then that's fine because each variable will have one word assigned to it:
$ readtest2 Enter some text: 1 2 3 The first word was: 1 The second word was: 2 The rest of the line was: 3
If you run out of words first this just means that the later variables will not be assigned a value from the input but will be set to empty (or NULL) instead:
$ readtest2 Enter some text: 1 2 The first word was: 1 The second word was: 2 The rest of the line was:
If there are more words than variables, then each variable has its expected word assigned to it, but then, rather than throw the extra words away they are appended to the value contained in the last variable in the list:
$ readtest2 Enter some text: 1 2 3 4 The first word was: 1 The second word was: 2 The rest of the line was: 3 4
The read command has a fairly wide definition for what it counts as a word - any string of characters delimited by a space, a tab or a newline. In fact, this list of delimiters is just the default, and the characters are stored in a shell variable called IFS. Because of this, it is possible to change the set of delimiters to other values, if required.
Command substitution allows the standard output from a pipeline to be used in place of the pipeline itself. A simple example might help to make this clear:
$ date Wed Jun 14 22:50:52 BST 1995 $ datestore=`date` $ echo $datestore Wed Jun 14 22:51:11 BST 1995
In this example, the date command is used to show the format of its output. Then, the same command is executed again, this time between a pair of backquotes (`), which makes the standard output from date available, here to be assigned to the variable datestore.
An alternative notation which achieves the same effect is to enclose the command or pipeline in parentheses and precede this with a dollar symbol:
$ datestore=$(date) $ echo $datestore Wed Jun 14 22:53:21 BST 1995
Another command which is used quite often in command substitution is called basename. What this command does is to take a full file pathname as a parameter and return the base file name with the path stripped off. For example:
$ basefile=`basename /usr/bin/man` $ echo $basefile man