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/07/12 05:58]
ormaaj wprintf
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 instance, if you use ''​%c'',​ you're actually asking for the first 8-bit 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'' ​flag with ''​%s''​ and ''​%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.+  ​* The a, A, e, E, f, F, g, and G conversions are supported by Bash, but not required by POSIX. 
 + 
 +  ​* 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''​. 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. 
 +<​code>​ 
 +# Illustrates Bash-like behavior. Redefining printf is usually unnecessary / not recommended. 
 +function printf { 
 +    case $1 in 
 +        -v) 
 +            shift 
 +            nameref x=$1 
 +            shift 
 +            x=$(command printf "​$@"​) 
 +            ;; 
 +        *) 
 +            command printf "​$@"​ 
 +    esac 
 +
 +builtin cut 
 +print $$ 
 +printf -v '​foo[2]'​ '​%d\n'​ "$(cut -d ' ' -f 1 /​proc/​self/​stat)"​ 
 +typeset -p foo 
 +# 22461 
 +# typeset -a foo=([2]=22461) 
 +</​code>​
  
-  * Length modifiers other than the above exception ​for ksh are simply dropped/ignored.+  * 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.
  
-  * mksh has no built-in printf.+  * 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.1342072699.txt
  • Last modified: 2012/07/12 05:58
  • by ormaaj