An Awk Primer/Output with print and printf

The simplest output statement is the by-now familiar "print" statement. There's not too much to it:

  • "Print" by itself prints the input line.
  • "Print" with one argument prints the argument.
  • "Print" with multiple arguments prints all the arguments, separated by spaces (or other specified OFS) when the arguments are separated by commas, or concatenated when the arguments are separated by spaces.

The "printf()" (formatted print) function is much more flexible, and trickier. It has the syntax:

   printf(<string>,<expression list>)

The "string" can be a normal string of characters:

   printf("Hi, there!")

This prints "Hi, there!" to the display, just like "print" would, with one slight difference: the cursor remains at the end of the text, instead of skipping to the next line, as it would with "print". A "newline" code ("\n") has to be added to force "printf()" to skip to the next line:

   printf("Hi, there!\n")

So far, "printf()" looks like a step backward from "print", and for do dumb things like this, it is. However, "printf()" is useful when precise control over the appearance of the output is required. The trick is that the string can contain format or "conversion" codes to control the results of the expressions in the expression list. For example, the following program:

   BEGIN {x = 35; printf("x = %d decimal, %x hex, %o octal.\n",x,x,x)}

—prints:

   x = 35 decimal, 23 hex, 43 octal.

The format codes in this example include: "%d" (specifying decimal output), "%x" (specifying hexadecimal output), and "%o" (specifying octal output). The "printf()" function substitutes the three variables in the expression list for these format codes on output.

  • The format codes are highly flexible and their use can be a bit confusing. The "d" format code prints a number in decimal format. The output is an integer, even if the number is a real, like 3.14159. Trying to print a string with this format code results in a "0" output. For example:
   x = 35;     printf("x = %d\n",x)      # yields:  x = 35    
   x = 3.1415; printf("x = %d\n",x)      # yields:  x = 3    
   x = "TEST"; printf("x = %d\n",x)      # yields:  x = 0
  • The "o" format code prints a number in octal format. Other than that, this format code behaves exactly as does the "%d" format specifier. For example:
   x = 255; printf("x = %o\n",x)          # yields:  x = 377
  • The "x" format code prints a number in hexadecimal format. Other than that, this format code behaves exactly as does the "%d" format specifier. For example:
   x = 197; printf("x = %x\n",x)          # yields:  x = c5
  • The "c" format code prints a character, given its numeric code. For example, the following statement outputs all the printable characters:
   BEGIN {for (ch=32; ch<128; ch++) printf("%c   %c\n",ch,ch+128)}
  • The "s" format code prints a string. For example:
   x = "jive"; printf("string = %s\n",x)  # yields:  string = jive
  • The "e" format code prints a number in exponential format, in the default format:
   [-]D.DDDDDDe[+/-]DDD

For example:

   x = 3.1415; printf("x = %e\n",x)       # yields:  x = 3.141500e+000
  • The "f" format code prints a number in floating-point format, in the default format:
   [-]D.DDDDDD

For example:

   x = 3.1415; printf("x = %f\n",x)       # yields:  f = 3.141500
  • The "g" format code prints a number in exponential or floating-point format, whichever is shortest.
  • A numeric string may be inserted between the "%" and the format code to specify greater control over the output format. For example:
   %3d    %5.2f    %08s    %-8.4s

This works as follows:

  • The integer part of the number specifies the minimum "width", or number of spaces, the output will use, though the output may exceed that width if it is too long to fit.
  • The fractional part of the number specifies either, for a string, the maximum number of characters to be printed; or, for floating-point formats, the number of digits to be printed to the right of the decimal point.
  • A leading "-" specifies left-justified output. The default is right-justified output.
  • A leading "0" specifies that the output be padded with leading zeroes to fill up the output field. The default is spaces.

For example, consider the output of a string:

   x = "Baryshnikov"
   printf("[%3s]\n",x)     # yields: [Baryshnikov]
   printf("[%16s]\n",x)    # yields: [     Baryshnikov]
   printf("[%-16s]\n",x)   # yields: [Baryshnikov     ]
   printf("[%.3s]\n",x)    # yields: [Bar]
   printf("[%16.3s]\n",x)  # yields: [             Bar]
   printf("[%-16.3s]\n",x) # yields: [Bar             ]
   printf("[%016s]\n",x)   # yields: [00000Baryshnikov]
   printf("[%-016s]\n",x)  # yields: [Baryshnikov     ]

—or an integer:

   x = 312
   printf("[%2d]\n",x)   # yields: [312]
   printf("[%8d]\n",x)   # yields: [     312]
   printf("[%-8d]\n",x)  # yields: [312     ]
   printf("[%.1d]\n",x)  # yields: [312]
   printf("[%08d]\n",x)  # yields: [00000312]
   printf("[%-08d]\n",x) # yields: [312     ]

—or a floating-point number:

   x = 251.67309
   printf("[%2f]\n",x)     # yields: [251.67309]
   printf("[%16f]\n",x)    # yields: [      251.67309]
   printf("[%-16f]\n",x)   # yields: [251.67309      ]
   printf("[%.3f]\n",x)    # yields: [251.673]
   printf("[%16.3f]\n",x)  # yields: [        251.673]
   printf("[%016.3f]\n",x) # yields: [00000000251.673]