Cover | Table of Contents | Colophon
http://www.bell-labs.com/history/unix.http://www.bell-labs.com/history/unix.$ who
george pts/2 Dec 31 16:39 (valley-forge.example.com)
betsy pts/3 Dec 27 11:07 (flags-r-us.example.com)
benjamin dtlocal Dec 27 17:55 (kites.example.com)
jhancock pts/5 Dec 27 17:55 (:32)
camus pts/6 Dec 31 16:22
tolstoy pts/14 Jan 2 06:42
wc
-l, to count just lines:$ who | wc -l Count users 6
| (pipe) symbol creates a pipeline between the two
programs: who's output becomes
wc's input. The result, printed
by wc, is the number of users logged in.$ cat > nusers Create the file, copy terminal input with cat who | wc -l Program text ^D Ctrl-D is end-of-file $ chmod +x nusers Make it executable $ ./nusers Do a test run 6 Output is what we expect
/bin/sh (the
standard shell) to run the program./bin/sh" mechanism is great when
there's only one shell. However, because current
Unix systems have multiple shells, there needs to be a way to tell
the Unix kernel which shell to use when running a particular shell
script. In fact, it helps to have a general mechanism that makes it
possible to directly invoke any programming
language interpreter, not just a command shell. This is done via a
special first line in the script file—one that begins with the
two characters #!.#!,
the kernel scans the rest of the line for the full pathname of an
interpreter to use to run the program. (Any intervening whitespace is
skipped.) The kernel also scans for a single
option to be passed to that interpreter. The kernel invokes the
interpreter with the given option, along with the rest of the command
line. For example, assume a csh script named /usr/ucb/whizprog,
with this first line:#! /bin/csh -f
/usr/ucb is included in
the shell's search path (described later). A user
might type the command whizprog -q /dev/tty01. The
kernel interprets the #! line and invokes
csh as follows:/bin/csh -f /usr/ucb/whizprog -q /dev/tty01
#! /bin/awk -f
awk program here
$ cd work ; ls -l whizprog.c -rw-r--r-- 1 tolstoy devel 30252 Jul 9 22:52 whizprog.c $ make ...
COMMAND=CD,ARG=WORK COMMAND=LISTFILES,MODE=LONG,ARG=WHIZPROG.C
cc -o
whizprog
whizprog.c). Options that
don't require an argument can be grouped together:
e.g., ls -lt whizprog.c rather than ls -l
-t whizprog.c (which works, but requires more typing).$ cd whizprog-1.1 $ patch --verbose --backup -p1 < /tmp/whizprog-1.1-1.2-patch
echo first arg is $1
echo tenth arg is ${10}
betsy because you really need
that flag you ordered from her:$ who | grep betsy Where is betsy? betsy pts/3 Dec 27 11:07 (flags-r-us.example.com)
$ cat > finduser Create new file #! /bin/sh # finduser --- see if user named by first argument is logged in who | grep $1 ^D End-of-file $ chmod +x finduser Make it executable $ ./finduser betsy Test it: find betsy betsy pts/3 Dec 27 11:07 (flags-r-us.example.com) $ ./finduser benjamin Now look for good old Ben benjamin dtlocal Dec 27 17:55 (kites.example.com) $
+
"—that is, a plus sign followed by a space.
(You can change what gets printed by assigning a new value to the
PS4 shell variable.) For example:$ sh -x nusers Run with tracing on + who Traced commands + wc -l 7 Actual output
set -x, and turn
it off again with set +x. This is more useful in
fancier scripts, but here's a simple program to
demonstrate:$ cat > trace1.sh Create script #! /bin/sh set -x Turn on tracing echo 1st echo Do something set +x Turn off tracing echo 2nd echo Do something else ^D Terminate with end-of-file $ chmod +x trace1.sh Make program executable $ ./trace1.sh Run it + echo 1st echo First traced line 1st echo Output from command + set +x Next traced line 2nd echo Output from next command
set -x is not traced, since tracing
isn't turned on until after that command completes.
Similarly, the set +x is traced, since tracing
isn't turned off until after it completes. The final
echo isn't traced, since tracing
is turned off at that point./usr/share/locale and
/usr/local/share/locale, or on commercial Unix
systems, /usr/lib/nls or
/usr/lib/locale. Details can be found in the
manual pages for setlocale(3),
catgets(3C), and
gettext(3C).#! first line should be used for all shell
scripts; this mechanism provides you with flexibility, and the
ability to write scripts in your choice of shell or other language.<, >,
>>, and |, with which we
expect you're really already familiar.$PATH. It's common to have a
personal bin directory in which to store your own
private programs and scripts, and to list it in
PATH by doing an assignment in your
.profile file.a." The notation lets you write a
single expression that can select, or match,
multiple data strings.$ cat myapp.data
# model units sold salesperson
xj11 23 jane
rj45 12 joe
cat6 65 chris
...
#
character represent comments, and are ignored. (This is a common
convention. The ability to have comment lines is helpful, but it
requires that your software be able to ignore such lines.) Each field
is separated from the next by an arbitrary number of space or tab
characters. The second convention is to use a particular delimiter
character to separate fields, such as a colon:$ cat myapp.data
# model:units sold:salesperson
xj11:23:jane
rj45:12:joe
cat6:65:chris
...
^ and $ usually apply to the
beginning and end of the string.sort -u would do that
job, but we also saw that the elimination is based on matching
keys rather than matching
records. The uniq command
provides another way to filter data: it is frequently used in a
pipeline to eliminate duplicate records downstream from a sort
operation:sort ... | uniq | ...
$ cat latin-numbers Show the test file tres unus duo tres duo tres $ sort latin-numbers | uniq Show unique sorted records duo tres unus $ sort latin-numbers | uniq -c Count unique sorted records 2 duo 3 tres 1 unus $ sort latin-numbers | uniq -d Show only duplicate records duo tres $ sort latin-numbers | uniq -u Show only nonduplicate records unus
$ sed -n -e 9991,10010p /usr/dict/words | fmt Reformat 20 dictionary words Graff graft graham grail grain grainy grammar grammarian grammatic granary grand grandchild grandchildren granddaughter grandeur grandfather grandiloquent grandiose grandma grandmother $ sed -n -e 9995,10004p /usr/dict/words | fmt -w 30 Reformat 10 words into short lines grain grainy grammar grammarian grammatic granary grand grandchild grandchildren granddaughter
/usr/dict/words, then
it probably has an equivalent file named
/usr/share/dict/words or
/usr/share/lib/dict/words.$ fmt -s -w 10 << END_OF_DATA Reformat long lines only > one two three four five > six > seven > eight > END_OF_DATA one two three four five six seven eight
$ echo This is a test of the emergency broadcast system | wc Report counts 1 9 49
$ echo Testing one two three | wc -c Count bytes 22 $ echo Testing one two three | wc -l Count lines 1 $ echo Testing one two three | wc -w Count words 4
$ wc /etc/passwd /etc/group Count data in two files 26 68 1631 /etc/passwd 10376 10376 160082 /etc/group 10402 10444 161713 total
LC_CTYPE to the desired
locale to influence wc's
interpretation of byte sequences as characters and word separators.