Backtick command encapsulation
Solution 1
Depends on your version of bash
:
bash-4.2$ echo `echo \`echo "uh!"\``
bash: !"\``: event not found
bash-4.3$ echo `echo \`echo "uh!"\``
uh!
In bash-4.3
, !"
is no longer eligible as a history event designator, so history expansion does not apply.
Other than that, it's just normal backtick nesting syntax. Inside backticks, the backslash character is overloaded (yet again) to do that nested expansion again.
You can nest as many levels as you want:
echo `echo \`echo \\\`echo \\\\\\\`echo whatever\\\\\\\`\\\`\``
Which is the cumbersome equivalent of:
echo $(echo $(echo $(echo $(echo whatever))))
However note that in both versions, the command substitution is subject to word splitting. So, you'd want to quote them to prevent it.
With bash
, dash
, pdksh
, yash
, zsh
, it's relatively easy:
echo "`echo "\`echo "\\\`echo "\\\\\\\`echo whatever\\\\\\\`"\\\`"\`"`"
With the Bourne or Korn shell, you also need to escape the "
though, so that becomes:
echo "`echo \"\`echo \\\"\\\`echo \\\\\\\"\\\\\\\`echo whatever\\\\\\\`\\\\\\\"\\\`\\\"\`\"`"
Compare with:
echo "$(echo "$(echo "$(echo "$(echo whatever)")")")"
Solution 2
This is interesting.
This expands to uh:
echo `echo \`echo uh\``
and not even
echo "`echo \`echo uh\``"
suppresses the inner expansion.
In both bash
and POSIX shells (dash), you have $()
as a nesting-friendly alternative to backticks.
Interestingly, the inner process substitution does not expand with $()
regardless of whether it's quoted or not or whether the inner substitution uses backticks or $()
:
$ echo $(echo \$\(echo uh\))
$(echo uh)
$ echo $(echo \`echo uh\`)
`echo uh`
The implicit expansion with backticks doesn't look very safe. I'd stick to $()
, especially if you want to nest.
Related videos on Youtube
![viuser](https://i.stack.imgur.com/Hcgqj.jpg?s=256&g=1)
viuser
Updated on September 18, 2022Comments
-
viuser almost 2 years
test@debian:~$ echo `echo \`echo "uh!"\`` uh!
How does the Bash do that? It seems that it first executes the expression in the non-escaped backticks, which gives back (the double-quotes "" are removed, right?):
`echo uh!`
So we have an input equivalent to:
test@debian:~$ echo `echo uh!`
(side note: really, why does it work? Because:
test@debian:~$ echo `echo uh!` -bash: !`: event not found
)
Then Bash executes the expression in backticks again, which gives:
test@debian:~$ echo uh!
Which finally gives us the output:
uh!
Is that right? And how could one encapsulate four
echo
-backtick-expression into each other?-
roaima over 8 yearsThis is
bash
right? Why not use$( ... )
and dispense entirely with the horrible mess that is backtick nesting?echo $(echo $(echo "uh!"))
-
viuser over 8 years@Pandya: You don't understand: I didn't forget it. It's what the bash, evaluating the outer backtick-expression, should give us.
-
roaima over 8 years
echo `echo 1 \`echo 2 \\\`echo 3 \\\\\\\`echo 4 "uh!" \\\\\\\` \\\` \` `
But I really would preferecho $(echo 1 $(echo 2 $(echo 3 $(echo 4 "uh!" ) ) ) )
-
-
Wildcard over 8 yearstl;dr is: Use
$(command)
rather than backticks. +1 for the last sentence. :)