(i in words) creates a loop that goes through the array words, setting i to each subscript of the array. This is different from most languages, where such a loop goes through each value in the array. The loop thus prints out each word followed by its frequency count. tolower was an addition to the One True awk (see below) made after the book was published. Match pattern from command line This program can be represented in several ways. The first one uses the Bourne shell to make a shell script that does everything. It is the shortest of these methods: #!/bin/sh pattern="$1" shift awk '/'"$pattern"'/ { print FILENAME ":" $0 }' "$@" The $pattern in the awk command is not protected by single quotes so that the shell does expand the variable but it needs to be put in double quotes to properly handle patterns containing spaces. A pattern by itself in the usual way checks to see if the whole line ($0) matches. FILENAME contains the current filename. awk has no explicit concatenation operator; two adjacent strings concatenate them. $0 expands to the original unchanged input line. There are alternate ways of writing this. This shell script accesses the environment directly from within awk: #!/bin/sh export pattern="$1" shift awk '$0 ~ ENVIRON["pattern"] { print FILENAME ":" $0 }' "$@" This is a shell script that uses ENVIRON, an array introduced in a newer version of the One True awk after the book was published. The subscript of ENVIRON is the name of an environment variable; its result is the variable's value. This is like the getenv function in various standard libraries and POSIX. The shell script makes an environment variable pattern containing the first argument, then drops that argument and has awk look for the pattern in each file. ~ checks to see if its left operand matches its right operand; !~ is its inverse. Note that a regular expression is just a string and can be stored in variables. The next way uses command-line variable assignment, in which an argument to awk can be seen as an assignment to a variable: #!/bin/sh pattern="$1" shift awk '$0 ~ pattern { print FILENAME ":" $0 }' "pattern=$pattern" "$@" Or You can use the -v var=value command line option (e.g. awk -v pattern="$pattern" ...). Finally, this is written in pure awk, without help from a shell or without the need