Backticks having different output from $() [duplicate] - bash

This question already has answers here:
What is the difference between $(command) and `command` in shell programming?
(6 answers)
Closed 7 years ago.
Can anyone explain the differences between `` (back-quotes) and $() in Linux?
Thank you very much!
By now , I just found that :
$echo `echo \\\\ `
\
$echo $(echo \\\\ )
\\

It's documented in man bash:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or
\. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all
characters between the parentheses make up the command; none are treated specially.
The more important difference is how they nest:
echo $(echo $(echo a))
echo `echo `echo a`` # Wrong
echo `echo \`echo a\``

Back-quotes(``) and $() can be both used for command-substitution, but they have minor difference.
Take the cases mentioned in the question as examples:
$echo `echo \\\\ `
The 1st and 3rd "\" will be treated as escapes, echo \\\\ will be evaluated as "\\"
Therefore, the above command is equal as:
$echo \\
And the first backslash is treated as escape, so the output is:
\
In the case of $(), there is a little tricky, what is evaluated inside $() will be passed as an argument to the outside command.
As an example:
$echo $(echo \\\\ )
What is inside the $() is evaluated as "\\", which is the same as the previous case. What's different is that "\\" will be passed directly to the outside echo command, the first backslash will not be treated as an escape.
Therefore we will got the output:
\\

Related

Why does a command with backslashes have different output between $() and ``(backticks)? [duplicate]

This question already has answers here:
Exactly how do backslashes work within backticks?
(2 answers)
Closed last month.
I found this:
echo `echo \\n`
output is n
while
echo $(echo \\n)
output is \n
I knew $() can perform nesting while `` can't, but there seems to be other differences.
The backquote is used in the old-style command substitution, e.g.
foo=`command`
The
foo=$(command)
syntax is recommended instead. Backslash handling inside $() is less surprising, and $() is easier to nest. See http://mywiki.wooledge.org/BashFAQ/082
About `...` syntax
In:
echo `echo \\n`
`echo \\n` return \n text
echo \n returns n
It's really different than echo -e "\n" who returns a ASCII LF character
About $(...) syntax
In:
echo $(echo \\n)
`echo \\n` return \n text but with $(...) returned like ONE token "\n"
echo "\n" returns \n

double backslashes of sed single-quoted command inside command substitutions get translated to a single backslash

printf '%s' 'abc' | sed 's/./\\&/g' #1, \a\b\c
printf '%s' "`printf '%s' 'abc' | sed 's/./\\&/g'`" #2, &&&
The expression inside the second backticks returns \a\b\c, and we have printf '%s' "\a\b\c", so it should print \a\b\c.
My question is: why does the second script print &&& ?
note:
I can get the second script work (prints \a\b\c) by prepending each backslash with another backslash, but I don't know why it's needed.
One related question:
why does this single quoted string get interpreted when it's inside of a command substitution
This is a good example to show difference between back-tick and $(cmd) command substitutions.
When the old-style backquoted form of substitution is used, backslash
retains its literal meaning except when followed by "$", "`", or "\".
The first backticks not preceded by a backslash terminates the command
substitution. When using the "$(COMMAND)" form, all characters between
the parentheses make up the command; none are treated specially.
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html
So take a look your example, I used echo instead of printf:
kent$ echo 'abc' | sed 's/./\\&/g'
\a\b\c
kent$ echo -E "`echo 'abc' | sed 's/./\\&/g'`"
&&&
kent$ echo -E "$(echo 'abc' | sed 's/./\\&/g')"
\a\b\c
You can see, the back-tick command substitution made your \\ as single \, thus together with the followed & it became \& (literal &)
Note that I used echo -E in order to disable the interpretation of backslash escapes so that the \a\b\c could be printed out.
Because on the second line :
you are saying:
printf '%s' 'abc' -> 'abc'
Then replace:
'abc'| sed 's/./\\&g' -> &&&
The s mean substitute
. mean one character
\\& by a char &
g mean multiple occurrence on the line
So you are saying:
Replace in abc each char by & multiple time on the same line
Explanation of \\\& :
Two backslashes become a single backslash in the shell which then in sed escapes the forward slash which is the middle delimiter.
\\& -> \& (which makes the forward & a regular character instead of a delimiter)
Three of them: The first two become one in the shell which then escape the third one in sed
\\\& -> \\&
Finally! don't forget that you command is under backquote:
The reason you have to escape it "twice" is because you're entering this command in an environment (such as a shell script) that interprets the double-quoted string once. It then gets interpreted again by the subshell.
From:
Why does sed require 3 backslashes for a regular backslash?

What is the difference between $(...) and `...`? [duplicate]

This question already has answers here:
What is the difference between $(command) and `command` in shell programming?
(6 answers)
Closed 7 years ago.
Using GNU bash 4.1.2, I get:
[roxma#VM_6_207_centos ~]$ echo `echo '\\'`
\
[roxma#VM_6_207_centos ~]$ echo $(echo '\\')
\\
The difference is documented in man bash:
When the old-style backquote form of substitution is used, backslash
retains its literal meaning except when followed by $, `, or \. The
first backquote not preceded by a backslash terminates the command
substitution. When using the $(command) form, all characters between
the parentheses make up the command; none are treated specially.
As per man bash, a similar difference between the two forms is found if $ follows the backslash:
$ echo `echo 'out: \$'`
out: $
$ echo $(echo 'out: \$')
out: \$
And the same if a backtick follows the backslash:
$ echo `echo 'out: \`'`
out: `
$ echo $(echo 'out: \`')
out: \`
Motivation
Since it could be useful to put a backtick as a character inside the command substitution, the backtick form has to have a way to escape a backtick. To make sure that one can put the escape character whereever one wants, then there also needs to be a way to escape the escape.

Backticks vs braces in Bash

When I went to answer this question, I was going to use the ${} notation, as I've seen so many times on here that it's preferable to backticks.
However, when I tried
joulesFinal=${echo $joules2 \* $cpu | bc}
I got the message
-bash: ${echo $joules * $cpu | bc}: bad substitution
but
joulesFinal=`echo $joules2 \* $cpu | bc`
works fine. So what other changes do I need to make?
The `` is called Command Substitution and is equivalent to $() (parenthesis), while you are using ${} (curly braces).
So all of these expressions are equal and mean "interpret the command placed inside":
joulesFinal=`echo $joules2 \* $cpu | bc`
joulesFinal=$(echo $joules2 \* $cpu | bc)
# v v
# ( instead of { v
# ) instead of }
While ${} expressions are used for variable substitution.
Note, though, that backticks are deprecated, while $() is POSIX compatible, so you should prefer the latter.
From man bash:
Command substitution allows the output of a command to replace the
command name. There are two forms:
$(command)
or
`command`
Also, `` are more difficult to handle, you cannot nest them for example. See comments below and also Why is $(...) preferred over ... (backticks)?.
They behave slightly differently in a specific case:
$ echo "`echo \"test\" `"
test
$ echo "$(echo \"test\" )"
"test"
So backticks silently remove the double quotes.
${} refer to Shell parameter expansion. Manual link:https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
The ‘$’ character introduces parameter expansion, command
substitution, or arithmetic expansion. The parameter name or symbol to
be expanded may be enclosed in braces, which are optional but serve to
protect the variable to be expanded from characters immediately
following it which could be interpreted as part of the name.
When braces are used, the matching ending brace is the first ‘}’ not
escaped by a backslash or within a quoted string, and not within an
embedded arithmetic expansion, command substitution, or parameter
expansion.
FULLPATH=/usr/share/X11/test.conf_d/sk-synaptics.conf
echo ${FULLPATH##*/}
echo ${FILENAME##*.}
First echo will get filename. second will get file extension as per manual ${parameter##word} section.
$(command)
`command`
refer to command substitution.
Bash performs the expansion by executing command in a subshell
environment and replacing the command substitution with the standard
output of the command, with any trailing newlines deleted.
https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html

Escape Function in Shell Programming

Why does the command
echo `echo \\z`
result in
z
instead of
\z
This is because `..` adds an additional escape level. $(..) does not, and is the preferred way of doing command expansion.
Given
echo `echo \\z`
we can remove a level of escaping and use $(..) to get:
echo $(echo \z)
and unquoted, \z is equivalent to z, so we end up with:
echo $(echo z)
Note that the outer echo has nothing to do with this. Backslashes are never treated specially when part of expansion data.
I suppose what you are actually running is:
echo `echo \\z`
If that's the case, in the inner echo, \\ was escaped to a \, and then in the external echo, \z results in "z". Same as if you run
echo \z
Btw, note the use of single commas to prevent escaping
echo '\\z'
which results in
\\z

Resources