gawk: Tee Program

1 
1 11.2.5 Duplicating Output into Multiple Files
1 ---------------------------------------------
1 
1 The 'tee' program is known as a "pipe fitting."  'tee' copies its
1 standard input to its standard output and also duplicates it to the
1 files named on the command line.  Its usage is as follows:
1 
1      'tee' ['-a'] FILE ...
1 
1    The '-a' option tells 'tee' to append to the named files, instead of
1 truncating them and starting over.
1 
1    The 'BEGIN' rule first makes a copy of all the command-line arguments
1 into an array named 'copy'.  'ARGV[0]' is not needed, so it is not
1 copied.  'tee' cannot use 'ARGV' directly, because 'awk' attempts to
1 process each file name in 'ARGV' as input data.
1 
1    If the first argument is '-a', then the flag variable 'append' is set
1 to true, and both 'ARGV[1]' and 'copy[1]' are deleted.  If 'ARGC' is
1 less than two, then no file names were supplied and 'tee' prints a usage
1 message and exits.  Finally, 'awk' is forced to read the standard input
1 by setting 'ARGV[1]' to '"-"' and 'ARGC' to two:
1 
1      # tee.awk --- tee in awk
1      #
1      # Copy standard input to all named output files.
1      # Append content if -a option is supplied.
1      #
1      BEGIN {
1          for (i = 1; i < ARGC; i++)
1              copy[i] = ARGV[i]
1 
1          if (ARGV[1] == "-a") {
1              append = 1
1              delete ARGV[1]
1              delete copy[1]
1              ARGC--
1          }
1          if (ARGC < 2) {
1              print "usage: tee [-a] file ..." > "/dev/stderr"
1              exit 1
1          }
1          ARGV[1] = "-"
1          ARGC = 2
1      }
1 
1    The following single rule does all the work.  Because there is no
1 pattern, it is executed for each line of input.  The body of the rule
1 simply prints the line into each file on the command line, and then to
1 the standard output:
1 
1      {
1          # moving the if outside the loop makes it run faster
1          if (append)
1              for (i in copy)
1                  print >> copy[i]
1          else
1              for (i in copy)
1                  print > copy[i]
1          print
1      }
1 
1 It is also possible to write the loop this way:
1 
1      for (i in copy)
1          if (append)
1              print >> copy[i]
1          else
1              print > copy[i]
1 
1 This is more concise, but it is also less efficient.  The 'if' is tested
1 for each record and for each output file.  By duplicating the loop body,
1 the 'if' is only tested once for each input record.  If there are N
1 input records and M output files, the first method only executes N 'if'
1 statements, while the second executes N'*'M 'if' statements.
1 
1    Finally, the 'END' rule cleans up by closing all the output files:
1 
1      END {
1          for (i in copy)
1              close(copy[i])
1      }
1