Classic Shell Scripting - Arnold Robbins [82]
If there are more input words than variables, the trailing words are assigned to the last variable. Desirable behavior falls out of this rule: using read with a single variable reads an entire input line into that variable.
Since time immemorial, the default behavior of read has been to treat a trailing backslash on an input line as an indicator of line continuation. Such a line causes read to discard the backslash-newline combination and continue reading from the next input line:
$ printf "Enter name, rank, serial number: " ; read name rank serno
Enter name, rank, serial number: Jones \
> Major \
> 123-45-6789
$ printf "Name: %s, Rank: %s, Serial number: %s\n" $name $rank $serno
Name: Jones, Rank: Major, Serial number: 123-45-6789
Occasionally, however, you want to read exactly one line, no matter what it contains. The -r option accomplishes this. (The -r option is a POSIX-ism; many Bourne shells don't have it.) When given -r, read does not treat a trailing backslash as special:
$ read -r name rank serno
tolstoy \
Only two fields provided
$ echo $name $rank $serno
tolstoy \ $serno is empty
More About Redirections
We have already introduced and used the basic I/O redirection operators: <, >, >>, and |. In this section, we look at the rest of the available operators and examine the fundamentally important issue of file-descriptor manipulation.
Additional Redirection Operators
Here are the additional operators that the shell provides:
Use >| with set -C
The POSIX shell has an option that prevents accidental file truncation. Executing the command set -C enables the shell's so-called noclobber option. When it's enabled, redirections with plain > to preexisting files fail. The >| operator overrides the noclobber option.
Provide inline input with << and <<-
Use program << delimiter to provide input data within the body of a shell script.
Such data is termed a here document. By default, the shell does variable, command, and arithmetic substitutions on the body of the here document:
cd /home Move to top of home directories
du -s * | Generate raw disk usage
sort -nr | Sort numerically, highest numbers first
sed 10q | Stop after first 10 lines
while read amount name
do
mail -s "disk usage warning" $name << EOF
Greetings. You are one of the top 10 consumers of disk space
on the system. Your home directory uses $amount disk blocks.
Please clean up unneeded files, as soon as possible.
Thanks,
Your friendly neighborhood system administrator.
EOF
done
This example sends email to the top ten "disk hogs" on the system, asking them to clean up their home directories. (In our experience, such messages are seldom effective, but they do make the system administrator feel better.)
If the delimiter is quoted in any fashion, the shell does no processing on the body of the input:
$ i=5
Set a variable
$ cat << 'E'OF
Delimiter is quoted
> This is the value of i: $i
Try a variable reference
> Here is a command substitution: $(echo hello, world)
Try command substitution
> EOF
This is the value of i: $i Text comes out verbatim
Here is a command substitution: $(echo hello, world)
The second form of the here document redirector has a trailing minus sign. In this case, all leading tab characters are removed from the here document and the closing delimiter before being passed to the program as input. (Note that only leading tab characters are removed, not leading spaces!) This makes shell scripts much easier to read. The revised form letter program is shown in Example 7-1.
Example 7-1. A form letter for disk hogs
cd /home Move to top of home directories
du -s * | Generate raw disk usage
sort -nr | Sort numerically, highest numbers first
sed 10q | Stop after first 10 lines
while read amount name
do
mail -s "disk usage warning" $name <<- EOF
Greetings. You are one of the top 10 consumers
of disk space on the system. Your home directory
uses $amount disk