The Syntax
Using $()
creates a new quoting context. Thus, double quotes inside a command substitution are completely independent of those outside it, and inside of closing the outer double quotes start a new and independent pair.
arg='one arg'
arg() { echo "arg: $1"; }
printf '? |%s|\n' "$(arg "$arg")"
...properly emits:
? |arg: one arg|
The Rationale (And History)
With the above syntax, adding additional nesting layers is easy:
printf '%s |%s|\n' "$(arg "$(arg "$arg")")"
With the pre-POSIX backtick syntax instead of $()
, your attempt #3 would have been correct:
printf '3 |%s|\n' "`arg \"$arg\"`"
However, needing to backslash-escape both quotes and nested backticks gets unworkable quickly as your nesting depth increases. Adding just one more nested arg
makes it:
printf '3a |%s|\n' "`arg \"\`arg \\\"$arg\\\"\`\"`"
Adding two additional layers (thus, three arg
function invocations total) is even worse, getting you into:
printf '3b |%s|\n' "`arg \"\`arg \\\"\\\`arg \\\\\\\"$arg\\\\\\\"\\\`\\\"\`\"`"
Whereas with the modern syntax, it's just:
printf '3b |%s|\n' "$(arg "$(arg "$(arg "$arg")")")"
Much, much easier.