Why doesn't printf escape newlines?
This is nothing to do with printf
, and everything to do with the argument that you have given to printf
.
In a double-quoted string, the shell turns \\
into \
. So the argument that you have given to printf
is actually hi\n
, which of course printf
then performs its own escape sequence processing on.
In a double-quoted string, the escaping done through \
by the shell is specifically limited to affecting the ␊, \
, `
, $
, and "
characters. You will find that \n
gets passed to printf
as-is. So the argument that you have given to printf
is actually hi\n
again.
Be careful about putting escape sequences into the format string for printf
. Only some have defined meanings in the Single Unix Specification. \n
is defined, but \c
is actually not, for example.
Further reading
- https://unix.stackexchange.com/a/359510/5132
- POSIX Shell: inside of double-quotes, are there cases where `\` fails to escape `$`, ```, `"`, `\` or `<newline>`?
- Why is a single backslash shown when using quotes
- Echo new line and string beginning \t
- Why does dash expand \\\\ differently to bash?
- https://unix.stackexchange.com/a/558665/5132
Within double quotes, \\n
is an escaped (quoted) backslash followed by a n
. This is given to printf
as \n
and printf
will output a newline.
Within double quotes (still), \n
is the string \n
. Again, printf
receives a \n
string and will print a newline.
Within double quotes, backslash is special only when preceding another backslash, a newline, or any of $
, `
or "
. "Special" means that it removes the special meaning of the next character. If a backslash precedes any other character (n
for example), then it's just a backslash character.
This is explained in the POSIX standard.
To print \n
in a printf
format string, use printf '\\n'
or printf "\\\\n"
, or use printf '%s' '\n'
In general, the printf
format string should be single quoted and any variable data should be given as additional arguments to be inserted into the format string:
printf 'This is how you write a newline: %s\n' '\n'