More small fry Unix commands
Cool tricks with read and wc
Mo continues his look at "small fry" Unix commands this month with an explanation of the
wc(word counter) utilities.
readcommand is usually used to accept keyboard input, but Mo shows you how it can be used to read input from a process as well. He also provides a nifty little word counting utility based on the
wccommand. (1,700 words)
read command is not actually a separate program in the Korn shell. It is
built into the Korn shell. Its purpose is to allow input information to be
read from standard input (usually the keyboard). In order to try out
ksh and press Enter.
Type the following command, and then enter a single word with no spaces as in
the example below. The command
read x causes input to be read from standard input
and assigned to the variable $x, which is then echoed to the screen.
$ read x; echo $x hello hello $
read is usually used in shell scripts to accept user input and assign it to a
variable. The following example, simpmenu, is a two-pick menu that uses
to accept the user's input.
A menu is displayed at lines 7 through 18. At line 19 the user selection is
accepted into the variable x and then one of two possible actions is executed
at lines 20 through 23 and 25 through 28. This action is repeated until the
user enters the number 9 as a menu pick. This is controlled at line 5. If $x is not
-ne) to 9 at line 5 then the loop continues to execute.
Note the additional
reads at lines 22 and 27. These
reads seem to have no
variable named for the input. The
read command supplies a default variable
named REPLY. That is used if no variable is named with the
read command. I am
read at lines 22 and 27 to give the user the opportunity to see
the last page of output before the screen is cleared.
1 # simpmenu 2 # a simple menu program 3 4 x=1 5 while [ $x -ne 9 ] 6 do 7 clear 8 echo 9 echo 10 echo "Enter your selection" 11 echo 12 echo 13 echo "1 Display directory" 14 echo "2 Display processes" 15 echo 16 echo 17 echo "9 Exit" 18 19 read x 20 if [ $x -eq 1 ] 21 then 22 ls -l|more ; echo "Press Enter" ; read 23 fi 24 25 if [ $x -eq 2 ] 26 then 27 ps -ef|more ; echo "Press Enter" ; read 28 fi 29 done
Using the default REPLY variable, the first exercise could be shortened to:
$ read; echo $REPLY hello hello $
read command can be used to read and fill more than one variable. Enter
the following command and then type four words separated by a space:
$ read x y z; echo $x; echo $y; echo $z one two three four one two three four $
read command reads in all of the words on a line and assigns them one by
one to the variables listed for the
read command. If there are more words than
there are variables, the remaining words are all assigned to the last variable. Thus $x=one, $y=two and $z=three and four.
This is true even with only one variable, as in the following listing. The $x
variable is the last variable associated with
read, and so it ends up with the
value one two three four:
$ read x; echo $x one two three four one two three four $
You can break up the list in $x by using
for, as follows:
$ read x; for name in $x; do echo $name; done one two three four one two three four $
In the multmenu listing, the user can actually enter more than one menu pick separated by spaces. At lines 20 through 34, the user selection is broken into pieces and each individual piece is processed in multiple passes.
1 # multmenu 2 # a multiple menu program 3 4 x=1 5 while [ $x -ne 9 ] 6 do 7 clear 8 echo 9 echo 10 echo "Enter your selection" 11 echo 12 echo 13 echo "1 Display directory" 14 echo "2 Display processes" 15 echo 16 echo 17 echo "9 Exit" 18 read x 19 for pick in $x 20 do 21 if [ $pick -eq 1 ] 22 then 23 ls -l|more ; echo "Press Enter" ; read 24 fi 25 if [ $pick -eq 2 ] 26 then 27 ps -ef|more ; echo "Press Enter" ; read 28 fi 29 if [ $pick -eq 9 ] 30 then 31 exit 32 fi 33 done 34 done
Reading from another process
read command possesses one other very powerful trick. It's possible to
start a process running that produces output, and then read that output as if
it were coming from the keyboard. This requires two steps:
readcommand has to be informed that it is reading from another process rather than from the keyboard
The listing for oldest uses this technique. The
ls -tr command lists the file
in a directory in oldest-to-newest order. The first entry in the list is
therefore the oldest. At line 4 the
ls -tr command is launched but ends with a
pipe bar and an ampersand (
|&). The ampersand indicates that the command is to
be detached and run as a background command. The pipe indicates that a
pipeline is to be created between oldest and the detached process. At line 6
read is issued with the -p flag meaning that it is to read from the pipe
rather than from standard input. The read only goes up to the first newline
character, so it only reads the first line that is output by the
1 # oldest 2 # names the oldest file 3 4 ls -tr|& 5 6 read -p x 7 8 echo "The oldest file is" $x
The next section on
wc includes another example of using
read command is more than simple input, and can be used for diverse tasks.
wc command provides a count of words, lines, and characters in a document.
In the listing below, log.txt contains 154 lines, 918 words, and 4431
ls -l listing also reveals the size of the file to be 4431
bytes in length.
$ wc log.txt 154 918 4431 log.txt $ ls -l log.txt -rw-r--r-- 1 mjb group 4431 Apr 12 14:35 log.txt
The word counter defines a word as any non-blank sequence of letters or numbers.
You may limit the output of
wc to a count of words, lines, or characters only
by using the -w,-l, and -c switches respectively. The default is
to display all three values. You may also display the results for more than one file as
the file name is displayed for each entry along with a total. The following
example displays the line counts for all files that start with log along
with a total:
$ wc -l log* 154 log.txt 5 logit.sh 159 total
wc utility is useful for authors. The listing for
ueditor is my own personal editor that I use to check word counts
(just kidding). It includes line numbers for explanation. The script
is invoked using the command
ueditor article.txt. At
wc is used to count words. The terminator
|& causes the
wc command to be started as
a background task, and opens a pipe from ueditor to the background
task in such a way that the results of the task can be read as input
by ueditor. The result is read at line 4. The
wc -w command
outputs two fields: the word count and the file name. These are read into
separate variables: $wrds and $name at line
4. The value in $wrds is tested at line 5; if it is less than
-lt) 2000, then words of encouragement are printed. If $wrds is
2000 or more, then the message contains some praise for your humble and hard-working
1 # ueditor 2 # checks if the article has 2000 words yet 3 wc -w $1|& 4 read -p $wrds $name 5 if [ $wrds -lt 2000 ] 6 then 7 echo "Only" $wrds "words! More, more I'm still not satisfied." 8 else 9 echo "A brilliant piece!" 10 fi
About the author
Mo Budlong, president of King Computer Services Inc., specializes in Unix and client/server consulting and training and currently publishes the COBOL Just In Time Course, a crash course for the Year 2000 problem as well as COBOL Dates and the Year 2000 which offers date solutions. Reach Mo at email@example.com.
If you have technical problems with this magazine, contact firstname.lastname@example.org