Bourne
|
Ash
|
#!
|
find
|
ARG_MAX
|
Shells
|
whatshell
|
portability
|
permissions
|
UUOC
|
ancient
| -
|
../Various
|
HOME
"$@
"
| echo/printf
|
set -e
|
test
|
tty defs
|
tty chars
|
$()
vs )
|
IFS
|
using siginfo
|
nanosleep
|
line charset
|
locale
echo(1) and printf(1)
Behaviour of the "echo" command or the shell built-in, respectively.
Availability of "printf", and implementation variations (especially handling of escape sequences).
2011年02月27日 (see recent changes)
1.) Variations in echo implementations
History
About the history, from Gunnar Ritter in <3B98D626.HL11B46E@bigfoot.de>
(rough translation by me), motivating this page:
"Research Unix -> 32v -> BSD had "-n",
PWB/Unix -> System III -> System V [had] the escape sequences
and then it became a jumble."
6th edition echo
research unix didn't know any features.
7th edition echo
implemented -n
PWB/Unix1.0 echo
(derived from 6th edition) implemented \n
, \c
, \\
, and 0円xx
System III (and SVR1) echo
knew \b
, \c
, \f
, \n
, \r
,
\t
, \\
, and 0円xx
Nowadays, echo(1)
is only portable if you omit flags and escape sequences.
Use printf(1)
instead, if you need more than plain text.
printf
was introduced with the Ninth Edition System
(reference in SUSv3).
It was added to more widely distributed Unix flavours with 4.3BSD-Reno and with SVR4.
Meanwhile printf
is required by POSIX
(SUSv1).
Portability
Traditional portability of echo is one issue. But what does POSIX say about options and backslash sequences?
POSIX doesn't support plain options:
SUSv2
states that "Implementations will not support any options."
Since SUSv3
this reads "Implementations shall not support any options."
But the BSD-like behaviour of suppressing newline with "-n
" is not always forbidden:
The behaviour with an operand containing "-n" and also the behaviour about backslash sequences
is implementation defined.
This gets the various traditional implementations into the boat.
But if the XSI option (X/Open System Interfaces) is supported on the system, then echo is well defined
and intended to behave
as specified by the System V Interface Definition, version 3:
"-n
" is not recognized and backslash sequences are defined.
More background about this distinction is
explained by Don Cragun on the austin group mailing list:
"The specification of 0円xxx in echo with the XSI option is intended to
behave as UNIX System V behaved as specified by the System V Interface
Definition, version 3 (SVID3).
(SVID3 was one of the base documents of
the original POSIX.2 standard, but since BSD systems and UNIX System V
systems had different behavior for echo,
the original POSIX.2 standard left the behavior unspecified
(allowing the then current implementations to continue to behave as they had).
The X/Open Portability Guide, Issue 3 continued to require the behavior as specified in SVID3.
When the original POSIX.2 and XPG3 were merged in a later revision of the standards, we got
the XSI option (which required the System V behavior);
but when XSI option support is not claimed the old BSD or System V behavior is allowed."
If you still have to supress newline with echo for some reason
(with the same script on different systems),
a possible workaround is the following code
( ${1+"$@"}
instead of "$@
"
addresses ancient pre-SVR3 shells):
if [ "X`echo -n`" = "X-n" ]; then
echo_n() { echo ${1+"$@"}"\c"; }
else
echo_n() { echo -n ${1+"$@"}; }
fi
A closer look at various implementations
(\a
is a representative for the other escape sequences)
- System specific echo implementations, and availability of printf:
Operating System
Bourne sh Korn sh (88) echo(1) printf(1)
-n -e \c \a \xxx
-n -e \c \a \xxx
-n -e \c \a \xxx
available
Version 7
(no built-in) N/A x
System III
(no built-in) N/A x x
SINIX V5.20
x x -e -e -e (N/A per default) x x -e -e -e
SunOS 4 ucb
[s4bsd]
x (N/A per default) x
SunOS 5 ucb
[s5bsd]
x x x x
SunOS 4 sysv
[s4sv]
x x (N/A per default) x x
SunOS 5 sysv
x x x x x x x x x
EP/IX 2.2.1AA
x x x x x x x x
Unicos 9.0.2.2
N/A x x x x x x x
HP-UX 8.07,9.03
x x x x x x x x
HP-UX 10/11.x
[hpux]
x x x x x x x x x
AIX 4.3
x x x x x x x x x
OSF1/V4, V5
x x x x x x x x x x
MUNIX 3.2 (SVR3)
x x x (N/A per default) x x x
AIX 3.2
x x x x x x x x x x x
IRIX 5.3, 6.5
x x x x x x x x x x x
OpenServer 506
x x x x x x x x x x x x
UnixWare 7.1.4
x x x x x x x x x x x
Almquist sh
pdksh
echo(1)
printf(1)
-n -e \c \a \xxx
-n -e \c \a \xxx
-n -e \c \a \xxx
FreeBSD 2.1
x x -e -e -e 5.2.14 see below
x x
FreeBSD 2.2, 4.3, 7.1
x x -e -e -e 5.2.14 see below
x x x
NetBSD 1.5.1, 5.1
x x -e -e -e 5.2.14 see below
x x
BSD/OS 4.1
x x -e -e -e 5.2.12 see below
x x
OpenBSD 2
[pdksh] 5.2.14 see below
x x
Minix 3.1.0
[minix3]
x x -e -e -
x x -e -e x
echo(1)
printf(1)
-n -e \c \a \xxx
POSIX XSI (SysV-like)
x x x
x
POSIX
? ? ? ?
x
GNU 2.0.15
x x -e -e -e
x
Busybox 1.01
[busybox]
x x -e -e -e
x
- Shell specific echo implementations:
Shell Built-ins
-n -e \c \a \xxx printf built-in
original ash x x x x
debian ash before 0.3.5-7 x x x x
debian ash/dash since 0.3.5-7 x x x x since ash-0.3.8-1
ksh86 EP/IX2.2.1AA x x
ksh88 [see above]
ksh93-d .. -q x x x x x
ksh93-r .. x x x x x x
pdksh(5.2.14) x x x x x
posh-0.5.4 x x x x
mksh-R28/R39/R52 x x x x x
bash-1.14.6/2.x/3.x/4.0 called as bash or sh x x -e -e -e since 2.02
zsh-3.0.8/4.3.2 called as zsh x x x x x since 4.1.0
zsh-3.0.8/4.3.2 called as sh x x -e -e -e since 4.1.0
printf built-in
NetBSD sh (almquist) [see above] added 11/'02, NetBSD 2.0
FreeBSD sh (almquist) [see above] removed 11/'01, FreeBSD 5.0
OpenBSD sh (pdksh) [see above] no
Footnotes for the first table
"-e" feature enabled when using this flag
"?" implementation defined
[hp-ux] On HP-UX 10, the POSIX shell (
/bin/sh
) behaves like the Korn shell
[s4bsd] SunOS 4 with
/usr/bin
preceding
/usr/5bin
in
PATH
.
The
echo
builtin mimics the according external command.
[s5bsd] SunOS 5 enables BSD compatibility, if /usr/ucb precedes
/usr/bin
in PATH.
On x86, this is also enabled, if
SYSV3
is set in the environment
[s4sv] SunOS 4 with
/usr/5bin
preceding
/usr/bin
in
PATH
.
The SysV version knows the escape sequences
"\b \c \f \n \r \t \v \xxx",
but not "\a" (
ASCII-BEL
).
[minix3]
printf(1)
has not been documented yet at the time of this writing (06/2010, v3.1.6).
It was added in jan '87 and released with v2.0.3. It's located in
/usr/bin/
.
[busybox]: busybox added
printf(1)
at about v0.27, may 1995.
2.) printf: variations in the handling of escape seqences
The following table lists tests results.
Keep in mind that some examples use unportable input to illustrate variations.
commandline
bash-2.05b
bash-4.0
ash-0.4.0
dash-
0.5.5.1
ksh93-k
ksh93-t
GNU core-
utils 5.97
OpenServer
5.0.6
OSF/1
V4.0B
EP/IX 2.2.1A
SunOS 5.9
printf '\a' | od -b -A n|sed 2d
007
007
007
007
007
007
007
007
007
007
007
printf '\b' | od -b -A n|sed 2d
010
010
010
010
010
010
010
010
010
010
010
printf '\t' | od -b -A n|sed 2d
011
011
011
011
011
011
011
011
011
011
011
printf '\n' | od -b -A n|sed 2d
012
012
012
012
012
012
012
012
012
012
012
printf '\v' | od -b -A n|sed 2d
013
013
013
013
013
013
013
013
013
013
013
printf '\f' | od -b -A n|sed 2d
014
014
014
014
014
014
014
014
014
014
014
printf '\r' | od -b -A n|sed 2d
015
015
015
015
015
015
015
015
015
015
015
printf '.\c.' | od -b -A n|sed 2d
056 134 143 056
056 134 143 056
056
056 134 143 056
056 143 056
056 156
056 134 143 056
134 143
056 134 143
056 134 143 056
056 134 143 056
printf '%b' '.\c.' | od -b -A n|sed 2d
056
056
056
056
056
056
056
056
056
056
056
printf '\d' | od -b -A n|sed 2d
134 144
134 144
134 144
134 144
144
144
134 144
134 144
134
134 144
134 144
printf '\g' | od -b -A n|sed 2d
134 147
134 147
134 147
134 147
147
147
134 147
134 147
134
134 147
134 147
printf '\h' | od -b -A n|sed 2d
134 150
134 150
134 150
134 150
150
150
134 150
134 150
134
134 150
134 150
printf '\i' | od -b -A n|sed 2d
134 151
134 151
134 151
134 151
151
151
134 151
134 151
134
134 151
134 151
printf '\j' | od -b -A n|sed 2d
134 152
134 152
134 152
134 152
152
152
134 152
134 152
134
134 152
134 152
printf '\k' | od -b -A n|sed 2d
134 153
134 153
134 153
134 153
153
153
134 153
134 153
134
134 153
134 153
printf '\l' | od -b -A n|sed 2d
134 154
134 154
134 154
134 154
154
154
134 154
134 154
134
134 154
134 154
printf '\m' | od -b -A n|sed 2d
134 155
134 155
134 155
134 155
155
155
134 155
134 155
134
134 155
134 155
printf '\o' | od -b -A n|sed 2d
134 157
134 157
134 157
134 157
157
157
134 157
134 157
134
134 157
134 157
printf '\p' | od -b -A n|sed 2d
134 160
134 160
134 160
134 160
160
160
134 160
134 160
134
134 160
134 160
printf '\q' | od -b -A n|sed 2d
134 161
134 161
134 161
134 161
161
161
134 161
134 161
134
134 161
134 161
printf '\s' | od -b -A n|sed 2d
134 163
134 163
134 163
134 163
040
163
134 163
134 163
134
134 163
134 163
printf '\u' | od -b -A n|sed 2d
134 165
134 165
N/A
134 165
165
000
134 165
134 165
134
134 165
134 165
printf '\w' | od -b -A n|sed 2d
134 167
134 167
134 167
134 167
167
167
134 167
134 167
134
134 167
134 167
printf '\y' | od -b -A n|sed 2d
134 171
134 171
134 171
134 171
171
171
134 171
134 171
134
134 171
134 171
printf '\z' | od -b -A n|sed 2d
134 172
134 172
134 172
134 172
172
172
134 172
134 172
134
134 172
134 172
printf '\e' | od -b -A n|sed 2d
033
033
134 145
134 145
145
033
033
033
033
033
033
printf '033円' | od -b -A n|sed 2d
033
033
033
033
033
033
033
033
033
033
033
printf '33円' | od -b -A n|sed 2d
033
033
033
033
033
033
033
033
033
033
033
printf '%b' '33円' | od -b -A n|sed 2d
033
033
033
033
134 063 063
134 063 063
033
033
N/A
033
033
printf '%b' '033円' | od -b -A n|sed 2d
033
033
033
033
033
033
033
033
033
033
033
printf '%b' '0033円' | od -b -A n|sed 2d
033
033
033
033
033
033
033
033
033
033
033
printf '0033円' | od -b -A n|sed 2d
033
003 063
003 063
003 063
003 063
003 063
003 063
003 063
003 063
003 063
033
printf '0033円' | od -b -A n|sed 2d
033
003 063
003 063
003 063
003 063
003 063
003 063
003 063
003 063
003 063
033
commandline
bash-2.05b
bash-4.0
ash-0.4.0
dash-
0.5.5.1
ksh93-k
ksh93-t
GNU core-
utils 5.97
OpenServer
5.0.6
OSF/1
V4.0B
EP/IX 2.2.1A
SunOS 5.9
printf '%d\n' '"a'
97
97
97
97
97
97
97
97
97
2146938837
97
<http://www.in-ulm.de/~mascheck/various/echo+printf/>
Sven Mascheck