Online Book Reader

Home Category

Classic Shell Scripting - Arnold Robbins [81]

By Root 843 0
data stream and passing it down the pipeline to the next one.

Reading Lines with read

The read command is one of the most important ways to get information into a shell program:

$ x=abc ; printf "x is now '%s'. Enter new value: " $x ; read x

x is now 'abc'. Enter new value: PDQ

$ echo $x

PDQ

* * *

read


Usage

read [ -r ] variable ...

Purpose

To read information into one or more shell variables.

Major options

-r

Raw read. Don't interpret backslash at end-of-line as meaning line continuation.

Behavior

Lines are read from standard input and split as via shell field splitting (using $IFS). The first word is assigned to the first variable, the second to the second, and so on. If there are more words than variables, all the trailing words are assigned to the last variable. read exits with a failure value upon encountering end-of-file.

If an input line ends with a backslash, read discards the backslash and newline, and continues reading data from the next line. The -r option forces read to treat a final backslash literally.

Caveats

When read is used in a pipeline, many shells execute it in a separate process. In this case, any variables set by read do not retain their values in the parent shell. This is also true for loops in the middle of pipelines.

* * *

read can read values into multiple variables at one time. In this case, characters in $IFS separate the input line into individual words. For example:

printf "Enter name, rank, serial number: "

read name rank serno

A typical use is processing the /etc/passwd file. The standard format is seven colon-separated fields: username, encrypted password, numeric user ID, numeric group ID, full name, home directory, and login shell. For example:

jones:*:32713:899:Adrian W. Jones/OSD211/555-0123:/home/jones:/bin/ksh

You can use a simple loop to process /etc/passwd line by line:

while IFS=: read user pass uid gid fullname homedir shell

do

... Process each user's line

done < /etc/passwd

This loop does not say "while IFS is equal to colon, read . . . " Rather, the assignment to IFS causes read to use a colon as the field separator, without affecting the value of IFS for use in the loop body. It changes the value of IFS only in the environment inherited by read. This was described in Section 6.1.1. The while loop was described in Section 6.4.

read exits with a nonzero exit status when it encounters the end of the input file. This terminates the while loop.

Placing the redirection from /etc/passwd at the end of the loop body looks odd at first. However, it's necessary so that read sees subsequent lines each time around the loop. Had the loop been written this way:

# Incorrect use of redirection:

while IFS=: read user pass uid gid fullname homedir shell < /etc/passwd

do

... Process each user's line

done

it would never terminate! Each time around the loop, the shell would open /etc/passwd anew, and read would read just the first line of the file!

An alternative to the while read ... do ... done < file syntax is to use cat in a pipeline with the loop:

# Easier to read, with tiny efficiency loss in using cat:

cat /etc/passwd |

while IFS=: read user pass uid gid fullname homedir shell

do

... Process each user's line

done

This is a general technique: any command can be used to pipe input into read. This is particularly useful when read is used in a loop. In Section 3.2.7, we presented this simple script for copying a directory tree:

find /home/tolstoy -type d -print | Find all directories

sed 's;/home/tolstoy/;/home/lt/;' | Change name, note use of semicolon delimiter

sed 's/^/mkdir /' | Insert mkdir command

sh -x Execute, with shell tracing

However, it can be done easily, and more naturally from a shell programmer's point of view, with a loop:

find /home/tolstoy -type d -print | Find all directories

sed 's;/home/tolstoy/;/home/lt/;' | Change name, note use of semicolon delimiter

while read newdir Read new directory name

do

mkdir $newdir Make new directory

done

(We note in passing that this

Return Main Page Previous Page Next Page

®Online Book Reader