$ printf "hi"
hi$ printf "hi\n"
hi
$ printf "hi\\n"
hi
Why doesn't the last line print hi\n?
Best Answer
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\nagain.
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.
Each sub-shell will access concurrently to the same /dev/stdout of the parent shell, so you can not ensure the order even inside the same function.
To ensure it you need a lock which enforce the mutual exclusion i.e. : all other processes won't start to write in /dev/stdout until the lock is released.
#!/bin/bash
function foo {
lockdir=/tmp/myscript.lock
mkdir "$lockdir" 2>/dev/null
while [ $? -ne 0 ]; do mkdir "$lockdir" 2>/dev/null; done
printf "Test line break: $1\nafter line break: $1\n\n"
rm -rf $lockdir
}
for VARIABLE in {1..30}
do
foo $VARIABLE &
done
wait
This will give this as a result :
$ bash plop1 2>/dev/null
Test line break: 5
after line break: 5
Test line break: 3
after line break: 3
Test line break: 11
after line break: 11
Test line break: 23
after line break: 23
Test line break: 14
after line break: 14
Test line break: 17
after line break: 17
Test line break: 24
after line break: 24
Test line break: 21
after line break: 21
Test line break: 27
after line break: 27
Test line break: 6
after line break: 6
Test line break: 2
after line break: 2
Test line break: 9
after line break: 9
Test line break: 26
after line break: 26
Test line break: 29
after line break: 29
Test line break: 20
after line break: 20
Test line break: 1
after line break: 1
Test line break: 12
after line break: 12
Test line break: 4
after line break: 4
Test line break: 13
after line break: 13
Test line break: 10
after line break: 10
Test line break: 15
after line break: 15
Test line break: 28
after line break: 28
Test line break: 25
after line break: 25
Test line break: 19
after line break: 19
Test line break: 18
after line break: 18
Test line break: 8
after line break: 8
Test line break: 7
after line break: 7
Test line break: 16
after line break: 16
Test line break: 22
after line break: 22
Test line break: 30
after line break: 30
Best Answer
This is nothing to do with
printf
, and everything to do with the argument that you have given toprintf
.In a double-quoted string, the shell turns
\\
into\
. So the argument that you have given toprintf
is actuallyhi\n
, which of courseprintf
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 toprintf
as-is. So the argument that you have given toprintf
is actuallyhi\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