The command
echo `echo \\\\\\\z`
is from this book , I don’t understand why it prints
\\z
when it get executed via the bash script.
I think it should print
\\\z
The command
echo `echo \\\\\\\z`
is from this book , I don’t understand why it prints
\\z
when it get executed via the bash script.
I think it should print
\\\z
Backticks effectively give you double processing of the backslashes. (Once when the main command line is processed, and another time when the command in the command substitution is.)
Like Kusalanda says, that's different for the $(..)
command substitution.
First, let's note that we appear to be talking about Bash's echo
, which by default doesn't process backslash escapes itself, so e.g. echo '\\'
passes \\
to echo
which prints \\
. If you used an echo
that deals with backslashes itself (like Bash with shopt -s xpg_echo
, or Dash, or zsh), you'd get that last \\
turned into \
and \z
as the output.
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by [a dollar sign, backtick or backslash].
So, in the command
echo `echo \\\\\\\z` # 7 backslashes
the \\
pairs get first reduced to single \
s, and the \z
stays as \z
(it's not followed by any of the three, so that backslash is literal). Then the command in the backticks runs through the shell again.
So the command in the command substitution ends up as
echo \\\\z # 4 backslashes
where the \\
pairs are reduced to single \
s, and the argument to echo
becomes \\z
(which is printed unchanged through the two echo
s, see caveat above).
You can see a similar result with a dollar sign, e.g.:
var=foo
echo `echo \$var`
prints foo
.
POSIX has also a weird example with single quotes:
echo `echo '\$x'`
prints $x
. (the single quotes don't protect the $
)
The $(...)
form of command substitution is saner, its contents only get processed once, so:
echo $(echo \\\\\\\z) # 7 backslashes
prints \\\z
(3), and
var=foo
echo $(echo \$var)
prints $var
.
Also see:
The initial echo command is handled by the shell, and so it correctly sees the multiple \
and reduces them to echo \\\z
.
At this point, the shell is no longer involved.
The echo command then sees \\\
, and so it it reduces that to the single \
, ie, you want a literal \
.
There is no need to escape the last \
, and so that then reduces to \\\z
.
echo `echo \\\\\\\z`
and echo $(echo \\\\\\\z)
?
– Kusalananda
Aug 07 '21 at 10:39
echo
does not care about backslashes at all unless used with -e
or the xpg_echo
option is set.
– Kusalananda
Aug 07 '21 at 11:06
$(...)
in place of backticks. – Kusalananda Aug 07 '21 at 10:36\\z
as output in the document that you link to, not\\\z
. – Kusalananda Aug 07 '21 at 11:09\z
on a shell that correctly implements POSIX. – schily Aug 08 '21 at 14:55dash -c 'echo `echo \\\\\\\z`'
– Aug 08 '21 at 21:01