printf
Arguments ¶Format strings for printf
and sprintf()
(see Using printf
Statements for Fancier Printing)
present a special problem for translation.
Consider the following:94
printf(_"String `%s' has %d characters\n", string, length(string)))
A possible German translation for this might be:
"%d Zeichen lang ist die Zeichenkette `%s'\n"
The problem should be obvious: the order of the format
specifications is different from the original!
Even though gettext()
can return the translated string
at runtime,
it cannot change the argument order in the call to printf
.
To solve this problem, printf
format specifiers may have
an additional optional element, which we call a positional specifier.
For example:
"%2$d Zeichen lang ist die Zeichenkette `%1$s'\n"
Here, the positional specifier consists of an integer count, which indicates which argument to use, and a ‘$’. Counts are one-based, and the format string itself is not included. Thus, in the following example, ‘string’ is the first argument and ‘length(string)’ is the second:
$ gawk 'BEGIN { > string = "Don\47t Panic" > printf "%2$d characters live in \"%1$s\"\n", > string, length(string) > }' -| 11 characters live in "Don't Panic"
If present, positional specifiers come first in the format specification, before the flags, the field width, and/or the precision.
Positional specifiers can be used with the dynamic field width and precision capability:
$ gawk 'BEGIN { > printf("%*.*s\n", 10, 20, "hello") > printf("%3$*2$.*1$s\n", 20, 10, "hello") > }' -| hello -| hello
NOTE: When using ‘*’ with a positional specifier, the ‘*’ comes first, then the integer position, and then the ‘$’. This is somewhat counterintuitive.
gawk
does not allow you to mix regular format specifiers
and those with positional specifiers in the same string:
$ gawk 'BEGIN { printf "%d %3$s\n", 1, 2, "hi" }' error→ gawk: cmd. line:1: fatal: must use `count$' on all formats or none
NOTE: There are some pathological cases that
gawk
may fail to diagnose. In such cases, the output may not be what you expect. It’s still a bad idea to try mixing them, even ifgawk
doesn’t detect it.
Although positional specifiers can be used directly in awk
programs,
their primary purpose is to help in producing correct translations of
format strings into languages different from the one in which the program
is first written.