created on | April 18, 2022 |
For output, two commands can be used: and . Both commands are available as a shell built-in and/or as a program, on most systems, both as a built-in and as a program.
In the beginning, echo did nothing but just output the arguments on the screen, separated by a blank and followed by a newline character after the last argument. Then someone thought it’s a good idea to add control sequences like , and for ‘tabs’, ‘carriage return’ and ‘clear to end of line’ to echo.
As it is always the case with any unix tool, it’s behaviour varies between different vendors or Unix systems. Some vendors chose to add options like to omit the trailing newline character, to enablde and to disable control sequences in arguments in whatever combination of options they felt like. So the behaviour of echo varies between the implementations of the vendors, the different shells like ash, bash, dash, zsh, csh, the different versions of each shell, and –to make the chaos complete– with which switches the shell or echo program is compiled and with which switches the shell is configured like i.e. for bash.
The POSIX spec for echo is quite clear about this:
" It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted. ... New applications are encouraged to use printf instead of echo. "
The Open Group Base Specifications Issue 7, 2018 edition, echo
printf is derived from the same name C function and it’s syntax is the same as it’s C sibling.
It is compatible not only across the Unix ecosystem, but also across different OS in general. That is, as long as one sticks to the printf features defined in POSIX.
The general form of printf is:
i.e.
prints the string , followed by a newline.
As long as don’t you use esoteric features with printf, you’re on the safe side.
The format follows this pattern: %[flags][width][.precision]<specifier>
specifier | output format | input | output |
---|---|---|---|
c | character | a | a |
s | string | hi there | hi there |
% | a percent character % followed by another % will output a single % | % | |
u | unsigned decimal integer | 42 | 42 |
d or i | signed decimal integer | -7 | -7 |
f | decimal floating point, lowercase | 123.45 | 123.45 |
e | scientific notation, lowercase | 123.45 | 1.234500e+2 |
E | Scientific notation, uppercase | 123.45 | 1.234500E+2 |
g | shortest representation of %e or %f | 1230000.45 | 1.23e+06 |
G | shortest representation of %E or %F | 1230000.45 | 1.23E+06 |
o | unsigned octal | 1984 | 3700 |
x | unsigned hexadecimal integer lowercase | 1984 | 7c0 |
X | unsigned hexadecimal integer uppercase | 1984 | 7C0 |
a | hexadecimal floating point, lowercase | 4.25 | 0x8.8p-1 |
A | hexadecimal floating point, uppercase | -4.25 | -0x8.8P-1 |
There is also a specifier F for decimal floating point, uppercase defined, but I do not have the slightest idea how a decimal floating number can be printed in upper case, so I didn’t include that one into the table above.
Surprisingly, the implementation of the specifiers e, E and even f and F is not mandatory:
" The a, A, e, E, f, F, g, and G conversion specifiers need not be supported. "
The Open Group Base Specifications Issue 7, 2018 edition, printf, extended description, 6.
On the other hand I haven’t come across a version of printf that didn’t support scientific notation or floating point decimals in 25 years and it’s pretty unlikely that one will dig out such an archaic version of printf.
flag | description |
---|---|
- | left-justify output. The default is to justify right |
+ | prepend a plus or minus sign (+ or -) to the output. By default, only negative numbers are prepended with a - sign. |
(space) | if no sign is going to be written, prepend the output with a blank (space). |
0 | left-pad the number with zeroes (0) instead of spaces when padding is specified |
# | used with o, x or X specifiers the value is preceeded with 0, 0x or 0X respectively for values different than zero |
width | description |
---|---|
positive integer | minimum number of characters to be printed. If the value to be printed is shorter, the output is padded with blanks (spaces). The output is not truncated if the result is larger. |
* | the width is not specified in the format string, but as an additional argument (integer) preceding the argument that has to be formatted. |
precision | applies to specifier(s) | description |
---|---|---|
.number | d, i, u, x, X, o | the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0. |
.number | a, A, e, E, f, F | the number of digits to be printed after the decimal point. The default is 6. |
.number | g, G | the maximum number of significant digits to be printed |
.number | s | the maximum number of characters to be printed. By default all characters are printed |
.* | the precision is not specified in the format string, but as an additional argument (integer) preceding the argument that has to be formatted |
If the period is specified without an value for precision, a precision of 0 is applied.
control sequence | function |
---|---|
\a | audible alert |
\b | backspace |
\f | form feed |
\n | newline (linefeed) |
\r | carriage return |
\t | tab |
\v | vertical tab |
\ | backslash |
printf with format string for three numeric arguments and one string argument:
output:
The Open Group Base Specifications Issue 7, 2018 edition, echo
The Open Group Base Specifications Issue 7, 2018 edition, printf
Sven Mascheck, Variations in echo implementations