More small fry Unix commands
Cool tricks with read and wc
Summary
Mo continues his look at "small fry" Unix commands this month with an explanation of the read and wc (word counter) utilities.
The read command 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 wc command. (1,700 words)
Last month I started a series on Unix's smaller but no less useful commands. This month we continue the series.
read
The 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 read ,
type 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 read
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
equal (-ne ) to 9 at line 5 then the loop continues to execute.
Note the additional read s at lines 22 and 27. These read s 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
only using 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
$
The 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
$
The 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
The 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:
- The process has to be started in a special way
- The
read command 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 ls -tr
command.
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 .
The read command is more than simple input, and can be used for diverse tasks.
wc
The 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
characters. An 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
The 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
line 3 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
author.
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
End of article.
Contact
us for a free consultation. |