commands:builtin:printf

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
commands:builtin:printf [2012/08/04 13:52]
ormaaj [Differences from C, and portability considerations] Even more portability.
commands:builtin:printf [2016/11/30 15:39] (current)
medievalist [differences from awk printf]
Line 30: Line 30:
 Thus, a typical ''​printf''​-call looks like: Thus, a typical ''​printf''​-call looks like:
 <​code>​ <​code>​
-printf "​Surname:​ %s\nName: %s\n" "​$SURNAME"​ "$LASTNAME"+printf "​Surname:​ %s\nName: %s\n" "​$SURNAME"​ "$FIRSTNAME"
 </​code>​ </​code>​
 where ''"​Surname:​ %s\nName: %s\n"''​ is the format specification,​ and the two variables are passed as arguments, the ''​%s''​ in the formatstring points to (for every format specifier you give, ''​printf''​ awaits one argument!). where ''"​Surname:​ %s\nName: %s\n"''​ is the format specification,​ and the two variables are passed as arguments, the ''​%s''​ in the formatstring points to (for every format specifier you give, ''​printf''​ awaits one argument!).
Line 106: Line 106:
 |''​%a''​|Interprets the associated argument as **double**, and prints it in the form of a C99 [[http://​www.exploringbinary.com/​hexadecimal-floating-point-constants/​ | hexadecimal floating-point literal]].| |''​%a''​|Interprets the associated argument as **double**, and prints it in the form of a C99 [[http://​www.exploringbinary.com/​hexadecimal-floating-point-constants/​ | hexadecimal floating-point literal]].|
 |''​%A''​|Same as ''​%a'',​ but print it like ''​%E''​| |''​%A''​|Same as ''​%a'',​ but print it like ''​%E''​|
-|''​%(FORMAT)T''​|output the date-time string resulting from using ''​FORMAT''​ as a format string for ''​strftime(3)''​. The associated argument is the number of seconds since Epoch, or ''​-1''​ (current time) or ''​-2''​ (shell startup time)|+|''​%(FORMAT)T''​|output the date-time string resulting from using ''​FORMAT''​ as a format string for ''​strftime(3)''​. The associated argument is the number of seconds since Epoch, or ''​-1''​ (current time) or ''​-2''​ (shell startup time). If no corresponding argument is supplies, the current time is used as default|
 |''​%%''​|No conversion is done. Produces a ''​%''​ (percent sign)| |''​%%''​|No conversion is done. Produces a ''​%''​ (percent sign)|
  
Line 162: Line 162:
 |''​\0<​NNN>''​|same as ''​\<​NNN>''​| |''​\0<​NNN>''​|same as ''​\<​NNN>''​|
 |''​\x<​NNN>''​|Interprets ''<​NNN>''​ as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)| |''​\x<​NNN>''​|Interprets ''<​NNN>''​ as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)|
-|''​\u<​NNNN>''​|same as ''​\x<​NNN>'',​ but **4 digits** ​ +|''​\u<​NNNN>''​|same as ''​\x<​NNN>'',​ but **4 digits**| 
-|''​\U<​NNNNNNNN>''​|same as ''​\x<​NNN>'',​ but **8 digits** ​ |+|''​\U<​NNNNNNNN>''​|same as ''​\x<​NNN>'',​ but **8 digits**
 + 
 +The following additional escape and extra rules apply only to arguments associated with a ''​%b''​ format: 
 + 
 +|''​\c''​|Terminate output similarly to the ''​\c''​ escape used by ''​echo -e''​. printf produces no additional output after coming across a ''​\c''​ escape in a ''​%b''​ argument.| 
 + 
 +  * Backslashes in the escapes: ''​\<​nowiki>'</​nowiki>'',​ ''​\"'',​ and ''​\?''​ are not removed. 
 +  * Octal escapes beginning with ''​\0''​ may contain up to four digits. (POSIX specifies up to three). 
 + 
 +These are also respects in which ''​%b''​ differs from the escapes used by [[syntax/​quoting#​ansi_c_like_strings ​$'​...'​]] style quoting.
  
 ===== Examples ===== ===== Examples =====
Line 268: Line 277:
 Please read the manpage of ''​strftime(3)''​ to get more information about the supported formats. Please read the manpage of ''​strftime(3)''​ to get more information about the supported formats.
  
-==== Using printf inside of awk ====+===== differences from awk printf =====
  
-Here'​s ​the gotcha:+Awk also derives its //​printf()//​ function from C, and therefore has similar format specifiers. ​ However, in all versions of awk the space character is used as a string concatenation operator, so it cannot be used as an argument separator. ​ **Arguments to awk printf must be separated by commas.** ​ Some versions of awk do not require printf arguments to be surrounded by parentheses,​ but you should use them anyway to provide portability. 
 + 
 +In the following example, the two strings are concatenated by the intervening space so that no argument remains to fill the format.
  
 <​code>​ <​code>​
- 
-$ printf "​%s\n"​ "​Foo"​ 
-Foo 
  
 $ echo "​Foo"​ | awk '{ printf "​%s\n"​ $1 }' $ echo "​Foo"​ | awk '{ printf "​%s\n"​ $1 }'
Line 285: Line 293:
 </​code>​ </​code>​
  
-One fix is to use commas to separate ​the format from the arguments:+Simply replacing ​the space with a comma and adding parentheses yields correct awk syntax.
  
 <​code>​ <​code>​
-$ echo "​Foo"​ | awk '{ printf "​%s\n",​ $1 }'+$ echo "​Foo"​ | awk '{ printf"​%s\n",​ $1 }'
 Foo Foo
 </​code>​ </​code>​
  
-Or, use **printf** ​the way that awk wants you to:+With appropriate metacharacter escaping ​the bash printf can be called from inside ​awk (as from perl and other languages that support shell callout) as long as you don't care about program efficiency or readability.
  
 <​code>​ <​code>​
-echo "​Foo"​ | awk '{ printf $1 "\n" }'+echo "​Foo"​ | awk '​{ ​system( "printf ​\"​%s\\n \" \"" ​$1 "​\"​" ​ ) }'
 Foo Foo
 </​code>​ </​code>​
- 
-But then you lose the ability to pad numbers, set field widths, etc. that **printf** has. 
  
 ===== Differences from C, and portability considerations ===== ===== Differences from C, and portability considerations =====
  
-  * There is no wide-character support (wprintf). For instanceif you use ''​%c''​you're actually asking for the first byte of the argument. Likewisethe maximum field width modifier (dot) in combination with ''​%s''​ goes by bytesnot characters. This limits some of printf'​s functionality to working with ascii only. ksh93'​s ''​printf''​ supports the ''​L''​ flag with ''​%s''​ and ''​%c''​ in order to treat precision as character widthnot byte count. zsh appears to adjust itself dynamically based upon LANG and LC_CTYPE. If LC_CTYPE=Czsh will throw "​character ​not in range" errors, and otherwise supports wide characters automatically if a variable-width encoding is set for the current locale.+  * The aAeEf, F, g, and G conversions are supported by Bashbut not required by POSIX.
  
-  * Length modifiers other than the above exception ​for ksh are simply dropped/ignored.+  * There is no wide-character support (wprintf). For instance, if you use ''​%c'',​ you're actually asking for the first byte of the argument. Likewise, the maximum field width modifier (dot) in combination with ''​%s''​ goes by bytes, not characters. This limits some of printf'​s functionality to working with ascii only. ksh93'​s ''​printf''​ supports the ''​L''​ modifier with ''​%s''​ and ''​%c''​ (but so far not ''​%S''​ or ''​%C''​) in order to treat precision as character width, not byte count. zsh appears to adjust itself dynamically based upon ''​LANG''​ and ''​LC_CTYPE''​. If ''​LC_CTYPE=C'',​ zsh will throw "​character not in range" errors, and otherwise supports wide characters automatically if a variable-width encoding is set for the current locale. 
 + 
 +  * Bash recognizes and skips over any characters present in the length modifiers specified by POSIX during format string parsing. 
 +<code c|builtins/printf.def> 
 +#define LENMODS "​hjlLtz"​ 
 +... 
 +/* skip possible format modifiers */ 
 +modstart = fmt; 
 +while (*fmt && strchr (LENMODS, *fmt)) 
 +fmt++; 
 +</​code>​
  
-  * mksh has no built-in printf by default (usually). There is an unsupported compile-time option to include a very poor basically unusable implementation. For the most part you must rely upon the system'​s ''/​usr/​bin/​printf''​ or equivalent. The mksh maintainer recommends using ''​print''​.+  * mksh has no built-in printf by default (usually). There is an unsupported compile-time option to include a very poorbasically unusable implementation. For the most part you must rely upon the system'​s ''/​usr/​bin/​printf''​ or equivalent. The mksh maintainer recommends using ''​print''​. The development version (post- R40f) adds a new parameter expansion in the form of ''​${name@Q}''​ which fills the role of ''​printf %q''​ -- expanding in a shell-escaped format.
  
   * ksh93 optimizes builtins run from within a command substitution and which have no redirections to run in the shell'​s process. Therefore the ''​printf -v''​ functionality can be closely matched by ''​var=$(printf ...)''​ without a big performance hit.   * ksh93 optimizes builtins run from within a command substitution and which have no redirections to run in the shell'​s process. Therefore the ''​printf -v''​ functionality can be closely matched by ''​var=$(printf ...)''​ without a big performance hit.
Line 332: Line 348:
 </​code>​ </​code>​
  
-  * Both the optional Bash loadable ''​print'', ​as well as ksh93'​s ''​print''​ have ''​-f''​ option which takes a ''​printf''​ format ​that can be used in combination with other options ​to ''​print''​. ​Unfortunately Bash provides no reliable way to tell if ''​print''​ is available or present in predictable location. zsh doesn'​t ​provide ​''​-f''​.+  * The optional Bash loadable ''​print'' ​may be useful for ksh compatibility and to overcome some of [[commands/​builtin/​echo | echo]]'​s portability pitfalls. Bash, ksh93, and zsh's ''​print''​ have an ''​-f''​ option which takes a ''​printf''​ format ​string and applies it to the remaining arguments. Bash lists the synopsis as: ''​print: print [-Rnprs] [-u unit] [-f format] [arguments]''​. ​However, only ''​-Rrnfu''​ are actually functional. Internally, ''​-p''​ is a noop (it doesn'​t ​tie in with Bash coprocs at all), and ''​-s''​ only sets a flag but has no effect. ''​-Cev''​ are unimplemented. 
 + 
 +  * Assigning to variables: The ''​printf -v''​ way is slightly different to the way using command-substitution. [[syntax:​expansion:​cmdsubst | Command substitution]] removes trailing newlines before substituting the text, ''​printf -v'' ​preserves all output. 
 ===== See also ===== ===== See also =====
  
  • commands/builtin/printf.1344088346.txt
  • Last modified: 2012/08/04 13:52
  • by ormaaj