gawk: Labels Program

 
 11.3.4 Printing Mailing Labels
 ------------------------------
 
 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, two across and 10 down.  The addresses are guaranteed to
 be no more than five 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 (SeeRecords).  It sets 'MAXLINES' to
 100, because 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 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
      ...
 
 The 'printf' format string '%-41s' left-aligns the data and prints it
 within a fixed-width field.
 
    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 two blank lines at the top and two 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
 
          delete line
      }
 
      # 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()
      }
 
    ---------- Footnotes ----------
 
    (1) "Real world" is defined as "a program actually used to get
 something done."