Here is a “real world”1 program. This script reads lists of names and addresses and generates mailing labels. Each page of labels has 20 labels on it, 2 across and 10 down. The addresses are guaranteed to be no more than 5 lines of data. Each address is separated from the next by a blank line.
The basic idea is to read 20 labels worth of data. Each line of each label
is stored in the line
array. The single rule takes care of filling
the line
array and printing the page when 20 labels have been read.
The BEGIN
rule simply sets RS
to the empty string, so that
awk splits records at blank lines
(see Records).
It sets MAXLINES
to 100, since 100 is the maximum number
of lines on the page (20 * 5 = 100).
Most of the work is done in the printpage
function.
The label lines are stored sequentially in the line
array. But they
have to print horizontally; line[1]
next to line[6]
,
line[2]
next to line[7]
, and so on. Two loops are used to
accomplish this. The outer loop, controlled by i
, steps through
every 10 lines of data; this is each row of labels. The inner loop,
controlled by j
, goes through the lines within the row.
As j
goes from 0 to 4, `i+j' is the j
-th line in
the row, and `i+j+5' is the entry next to it. The output ends up
looking something like this:
line 1 line 6 line 2 line 7 line 3 line 8 line 4 line 9 line 5 line 10 ...
As a final note, an extra blank line is printed at lines 21 and 61, to keep the output lined up on the labels. This is dependent on the particular brand of labels in use when the program was written. You will also note that there are 2 blank lines at the top and 2 blank lines at the bottom.
The END
rule arranges to flush the final page of labels; there may
not have been an even multiple of 20 labels in the data:
# labels.awk --- print mailing labels # Each label is 5 lines of data that may have blank lines. # The label sheets have 2 blank lines at the top and 2 at # the bottom. BEGIN { RS = "" ; MAXLINES = 100 } function printpage( i, j) { if (Nlines <= 0) return printf "\n\n" # header for (i = 1; i <= Nlines; i += 10) { if (i == 21 || i == 61) print "" for (j = 0; j < 5; j++) { if (i + j > MAXLINES) break printf " %-41s %s\n", line[i+j], line[i+j+5] } print "" } printf "\n\n" # footer for (i in line) line[i] = "" } # main rule { if (Count >= 20) { printpage() Count = 0 Nlines = 0 } n = split($0, a, "\n") for (i = 1; i <= n; i++) line[++Nlines] = a[i] for (; i <= 5; i++) line[++Nlines] = "" Count++ } END \ { printpage() }