Classic Shell Scripting - Arnold Robbins [136]
}
Now name_by_telephone contains tab-separated lists of people with the same telephone number.
Other Control Flow Statements
We have already discussed the break and continue statements for interrupting the control flow in iterative statements. Sometimes, you need to alter the control flow in awk's matching of input records against the patterns in the list of pattern/action pairs. There are three cases to handle:
Skip further pattern checking for this record only
Use the next statement. Some implementations do not permit next in user-defined functions (described in Section 9.8).
Skip further pattern checking for the current input file
gawk and recent releases of nawk provide the nextfile statement. It causes the current input file to be closed immediately, and pattern matching restarts with records from the next file on the command line.
You can easily simulate the nextfile statement in older awk implementation, with some loss of efficiency. Replace the nextfile statement with SKIPFILE = FILENAME; next, and then add these new pattern/action pairs at the beginning of the program:
FNR = = 1 { SKIPFILE = "" }
FILENAME = = SKIPFILE { next }
The first pattern/action pair resets SKIPFILE to an empty string at the start of each file so that the program works properly if the same filename appears as two successive arguments. Even though records continue to be read from the current file, they are immediately ignored by the next statement. When end-of-file is reached and the next input file is opened, the second pattern no longer matches, so the next statement in its action is not executed.
Skip further execution of the entire job, and return a status code to the shell
Use the exit n statement.
User-Controlled Input
awk 's transparent handling of input files specified on the command line means that most awk programs never have to open and process files themselves. It is quite possible to do so, however, through awk's getline statement. For example, a spellchecker usually needs to load in one or more dictionaries before it can do its work.
getline returns a value and can be used like a function, even though it is actually a statement, and one with somewhat unconventional syntax. The return value is +1 when input has been successfully read, 0 at end-of-file, and -1 on error. It can be used in several different ways that are summarized in Table 9-3Table 9-3.
Table 9-4. getline variations
Syntax
Description
getline
Read the next record from the current input file into $0, and update NF, NR, and FNR.
getline var
Read the next record from the current input file into var, and update NR and FNR.
getline < file
Read the next record from file into $0, and update NF.
getline var < file
Read the next record from file into var.
cmd | getline
Read the next record from the external command, cmd, into $0, and update NF.
cmd | getline var
Read the next record from the external command, cmd, into var.
Let's look at some of these uses of getline. First, we pose a question, and then read and check the answer:
print "What is the square root of 625?"
getline answer
print "Your reply, ", answer ", is", (answer = = 25) ? "right." : "wrong."
If we wanted to ensure that input came from the controlling terminal, rather than standard input, we instead could have used:
getline answer < "/dev/tty"
Next, we load a list of words from a dictionary:
nwords = 1
while ((getline words[nwords] < "/usr/dict/words") > 0)
nwords++
Command pipelines are a powerful feature in awk. The pipeline is specified in a character string, and can contain arbitrary shell commands. It is used with getline like this:
"date" | getline now
close("date")
print "The current time is", now
Most systems limit the number of open files, so when we are through with the pipeline, we use the close( ) function to close the pipeline file. In older awk implementations, close was a statement, so there is no portable way to use it like a function and get a reliable return code