In the format argument of printf
, only the %
and \
characters are special (no, "
is not special and \"
is unspecified per POSIX).
But, two important notes.
In most printf
implementations¹, it's the byte values for \
and %
that are special and the POSIX specification could even be interpreted as requiring it as it requires the printf
utility to be an interface to the printf(3)
C function and not wprintf(3)
for instance (like it requires %.3s
to truncate to 3 bytes and not 3 characters).
In some character encodings including BIG5 and GB18030, there are hundreds of characters that contain the encoding of backslash, and to escape those for printf
, you'd need to insert a \
before each 0x5c
byte within the encoding of those characters!
For instance in BIG5-HKSCS, as used for instance in the zh_HK.big5hkscs
(Hong Kong) locale, all of Ěαжふ㘘㙡䓀䨵䪤么佢俞偅傜兝功吒吭园坼垥塿墦声娉娖娫嫹嬞孀尐岤崤幋廄惝愧揊擺暝枯柦槙檝歿汻沔涂淚滜潿瀙瀵焮燡牾狖獦珢珮琵璞疱癧礒稞穀笋箤糭綅縷罡胐胬脪苒茻莍蓋蔌蕚螏螰許豹贕赨跚踊蹾躡鄃酀酅醆鈾鎪閱鞸餐餤駹騱髏髢髿鱋鱭黠﹏
contain byte 0x5c (which is also the encoding of \
).
With most printf
implementations, in that locale, printf 'αb'
doesn't output αb
but byte 0xa3
(the first byte of the encoding of α
) followed by the BS character (the expansion of \b
).
$ LC_ALL=zh_HK.big5hkscs luit
$ locale charmap
BIG5-HKSCS
$ printf 'αb' | LC_ALL=C od -tx1 -tc
0000000 a3 08
243 \b
0000002
Best is to avoid using (and even installing / making available) those locales as they cause all sorts of bugs and vulnerabilities of that sort.
Some printf
implementations support options, and even those that don't are required to support --
as the option delimiter. So printf --
won't output --
but likely report an error about a missing format argument. So if you can't guarantee your format won't start with -
, you have to use the --
option delimiter:
printf -- "$escaped_format" x y...
In any case, if you want to print arbitrary strings, you'd use:
printf '%s\n' "$data" # with terminating newline
printf %s "$data" # without
There's no character that is special in the string passed to %s
(though note that with the exception of the printf
builtin of zsh
, you can't pass the NUL character in any of printf
arguments).
Note that while the canonical way to enter a literal \
is with \\
and a literal %
with %%
, on ASCII-based systems, you can also use \134
and \45
and with some printf
implementations \x5c
, \x25
, or \x{5c}
, \x{25}
, or (even on non-ASCII systems): \u005c
, \u0025
or \u{5c}
, \u{25}
.
¹ yash
's printf
builtin being the only exception I am aware of.
\' \" \?
.......... a good search engine for this kind of stuff is http://symbolhound.com/ – jsotola Jan 16 '19 at 04:32