2.4 Notes: More on printf

The Format String

The format string in printf is a number of tokens which describe how to 
print the variables you supply, and whatever else you want. Each variable 
format specifier starts with a %, is followed by zero or more of the 
optional modifiers, and ends with a conversion specifier. 

A typical format string could look like this: 

         "foo is %d"

Printed, it may look something like: 'foo is 12'. The %d is replaced by a 
variable or constant specified after the format string argument. In this 
case, you would say: 

         printf "foo is %d", 12

so that %d is replaced with the value of 12. You can put as many specifiers in 
the format string as you like, with the same number of following arguments as 
there are specifiers. An example: 

         printf "%d %s %f" 12 "12" 12.0

Conversion Specifiers

You put these in your Format String. Each one, except %%, is replaced by
the corresponding value in the printf argument list. 

     %% prints a single % (percent sign). 
     %b prints the arguments as strings allowing backquote interpretion.
     %c prints a single character with the given ASCII number 
		(66 is printed as B, for example). 
     %s prints a given string 
     %d a signed integer in decimal 
     %u an unsigned (can't be negative) integer in decimal 
     %o an unsigned integer in octal 
     %x an unsigned integer in hexadecimal 
     %e a floating point number in scientific notation 
     %f a floating point number in fixed decimal notation 
     %g same as %e or %f, whichever printf thinks is best. 
     %X is the same as %x, except it uses upper-case letters 
     %E like %e, but with an upper-case 'E' 
     %G same as %E when scientific notation is used for the value. 

 Others that simply exist for backward compatibility:

     %i synonym for %d 

 Format Specifiers

     % - a percent sign. This is required, of course. 
     Zero or more of the following: 
        '#' (pound sign): Specifies that the value should be converted to an 
			  'alternate form.' This has no effect on 'c',
        'd', 'i', 'n', 'p', 's', and 'u' conversions. For 'o' (octal) 
				        conversions, this prepends a '0' to the
        				beginning. For 'x' and 'X' (hexadecimal),
					0x or 0X is prepended to the value. For
				        'e', 'E', 'f', 'g' and 'G', the value 
					is always printed with a trailing 
					decimal point (.), even if no numbers 
					follow it. For 'g' and 'G', trailing 
					zeros are not removed from the result. 

        printf "%x"  10              # prints just 'a', versus:
        printf "%#x"  10              # prints '0xa'

        '0' (zero): To specify zero-padding on a digit. The converted value is 
			padded on the left with the specified number of zeros 
			minus the number of digits to be printed. This is 
			described in more detail below. 

        printf "%03d" 7              # prints '007' 
        printf "%03d" 153            # prints '153'

        '-' (minus): Specifies a negative field width. This indicates the value
			should be left-adjusted on the boundary, versus the 
			default right-adjusted. See below for more on how to 
			specify field widths. 

        printf "%5s"  'foo'          # prints '  foo'
        printf "%-5s"  'foo'          # prints 'foo  '

        ' ' (a space): To specify that a blank should be left before a positive
			 number. 

        printf "% d" 7                # prints ' 7'
        printf "% d" -7               # prints '-7'

        '+' (plus sign): This specifies that a sign always be placed before the
			 value. '+' overrides ' ' (space) if both are used. 

        printf "%+d" 7          # prints '+7'

     A decimal digit specifying the minimum field width. Using the '-' modifier
	(see above) will left-align the value, otherwise it is right-aligned. 
	With the '0' modifier for numeric conversions, the value is 
	right-padded with zeros to fill the field width. 

     printf "%5s" 'foo'          # prints '  foo'
     printf "%-5s" 'foo'         # prints 'foo  '

     A precision value in the form of a period ('.'), followed by an optional 
	digit string. If the digit string is omitted, a precision of zero is 
	used. This specifies the minimum number of digits to print for 'd', 
	'i', 'o', 'u', 'x', and 'X' conversions. For 'e', 'E', and 'F' 
	conversions, it is the number of digits to appear after the decimal 
	point. For 'g' and 'G' conversions, it specifies the maximum number 
	of signifigant digits. For the 's' (string) conversion, it is the
        maximum number of characters of the string to print. Use the latter 
	to make sure long strings don't exceed their field width. 

     printf "%03.d" 7              # prints '007'
     printf "%.2f" 3.66666       # prints '3.67'
     printf "%.3s" 'foobar'       # prints 'foo'

     Finally, the required conversion specifier. Valid conversions are listed 
	in the previous section. 

 Leading Zeros

Say you have a number, something like 642, and you want to output it as 
00642 instead. The %0nC specifier syntax lets you do just that, where 'n' 
is the field width, and C is the conversion specifier you want to use. A 
field width is the minimum (in this case) number of characters the value 
should fill. Any less than that, and the remainder is filled by prepending 
zeros on your value until it fits perfectly. 

         printf "%05d" 642            # outputs '00642'

You should note that certain conversions, like %f, are a little trickier. 
Floating point numbers (with %f) are always outputted with 6 places after 
the decimal point, unless you specify a precision with the '.' modifier 
(see below for a discussion of the '.' precision modifier). In other words, 
printing a value of '2' as %f will actually output as 2.000000. This means 
you have to take into account, when specifying the field width, that there 
are already 7 characters tacked on. To get the value of 2 to print with one 
leading zero, you have to use a field width of 9 (7 for the '.' and 6 zeros, 
1 for the '2', and 1 for the leading zero). 

All other specifiers act in this way, too. To find out how many characters 
are output by default for a specifier, output a value of 0 (zero) for it 
and count how many characters there are: 

         # this outputs: '0, 0.000000, 0.000000e+00'
         printf "%d, %f, %e" 0 0 0

         printf "There are %d characters\n" 12

Which should tell you there are 12 characters for 0 in scientific notation. 

Padding with spaces

This is more or less the same as leading zeros, except it uses leading (or, 
if told, trailing) spaces to complete the field width. This is useful for 
lining up multiple lines of data into a report, for instance (though in that 
case, you may also want to specify a maximum field width to truncate long 
values - more on that below). The syntax is just like leading zeros, but 
drop the leading zero: 

         printf "%6s" 'foo'         # prints '   foo'

By default, leading spaces are used, so values appear to be right-aligned in 
their field. To reverse this, put a '-' sign before the field width: 

         printf "%-6s" 'foo'          # prints 'foo   '

For numeric values with default precision, like %f and %e, act here just 
like they do with leading zeros. %f, for example, won't have any padding 
unless you put a field width of more than 8. 

 Precision Modifier

The precision modifier tells printf how many digits you want after 
the decimal point, if its a floating point specifier. If there are more 
digits than you specified, the value is rounded. If there are less, zeros 
are used to fill the space. 

         printf "%.2f" 9.333333              # prints '9.34'
         printf "%.2f" 9                      # prints '9.00'

For decimal values, the precision modifier has the same effect as the '0' 
modifier described above: 

         printf "%03.f" 7                     # prints 007

For string values, it has the nice effect of specifying a maximum field 
width, where it will only print out the first n characters of the string. 
In combonation with the field width modifier described above, you can have 
a well-behaved-under-all-circumstances string field. 

         printf "%.3s" 'foobar'               	# prints 'foo'
         printf "%.10s" 'foobar'              	# prints 'foobar'
         printf "%5.5s %5.5s" 'foobar' 'baz'	 # prints 'fooba   baz'


Octal and Hexadecimal

You can convert your decimal based values to Hexadecimal and Octal values 
using printf and sprintf. To do so, specify the conversion as 
%o for octal, and %x for hexadecimal. %X is equivilant to %x, except the 
result is printed using capital letters. 

         printf "%x" 15       # prints 'f'
         printf "%X" 15       # prints 'F'
         printf "%o" 15       # prints '17'

As explained in the Format Modifiers section, using a '#' (pound sign) right 
after the % will convert the value to "alternate form." For %x and %X, it 
will prepend to the value '0x' and '0X' respectively. For %o, a single 
leading '0' (zero) is added. The extra characters using the # modifier are 
considered part of the field width. 

         printf "%#x" 15      # prints '0xf'
         printf "%#o" 15      # prints '017'
         printf "%#4x" 15     # prints ' 0xf'

In the last example, the field width of 4 is specified. Since the # modifier 
adds two extra characters to the value, it ends up taking 3 characters in 
total. Thus the single leading space. 
 

Questions? Robert Katz: rkatz@ned.highline.edu
Last Update July 1, 2003