4

The question is basically, how does bash deal with double quotes and brackets?

I couldn't come up with a better example, so apologies about that, but imagine something like this:

"$(echo "${foo}")"

What happens there? Is ${foo} technically out of the quotation scope? Is bash smart enough to also consider that it is inside of the parentheses and work inside-out? Would \"${foo}\" work better?

I've tried Googling this, but no luck. Please note that this is different from just nested quoting questions, as it includes expansion.

Thanks!

spalac24
  • 1,076
  • 1
  • 7
  • 16
  • I have a feeling that you are understanding it wrong. Can you clarify your point of view? – Jahid Jul 31 '17 at 09:04
  • I want to prevent word-splitting. Twice. So the example that I shown is part of a more complicated command invocation. I.e. I want the result of `$(echo ${foo})` to be interpreted as one word, but also ${foo} should be interpreted as one word. This is mostly out of curiosity for how bash escaping works, not that I can't work around this by e.g. temporary variables. – spalac24 Jul 31 '17 at 09:11

3 Answers3

4

Each command substitution establishes a new quoting context, so the correct way to avoid word splitting inside nested command substitutions is to use double quotes.

In this example, white space is preserved:

$ echo "$(echo "$(echo 'foo     bar')")" # outer echo sees 'foo     bar'
foo     bar

However, missing any of the double quotes means that the string is split by the shell:

$ echo $(echo "$(echo 'foo     bar')") # outer echo sees 'foo' 'bar'
foo bar
$ echo "$(echo $(echo 'foo     bar'))" # middle echo sees 'foo' 'bar'
foo bar

echo outputs each argument, separated by a spaces, which is where the single space between "foo" and "bar" comes from.

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
3

The example you gave does save you from word splitting completely:

"$(echo "${foo}")"

while,

"$(echo ${foo})"

would save you from word splitting on the output but not on the variable $foo.

$() opens a subshell and you need to quote your vars in this subshell too. Consider the following example:

"$(echo "$(echo "$foo")")"

None of the pair of quotes above is optional, if you miss any of them, you will be subject to word splitting.

Consider another example:

"$foo var in same shell, $(cmd) - this output is also in the same shell"

In above, $foo and the output of cmd are safe, but if the cmd includes another variable inside $(), then that variable will need to be quoted.

Jahid
  • 21,542
  • 10
  • 90
  • 108
-2

What is foo? Is it a value? try

"$(echo "$\{foo\}")"
Snow
  • 71
  • 1
  • 11
  • 1
    What do you mean value? If you mean a variable, then yes. Any reason you put escaping before brackets and not quotes? See my other comment for clarification: I want to prevent word-splitting. Twice. So the example that I shown is part of a more complicated command invocation. I.e. I want the result of $(echo ${foo}) to be interpreted as one word, but also ${foo} should be interpreted as one word. This is mostly out of curiosity for how bash escaping works, not that I can't work around this by e.g. temporary variables. – spalac24 Jul 31 '17 at 09:14
  • @Snow can you please (try) (or if not; PM me and I can help formulate your answer if you want) try - try to elaborate ; and write more (I.e include references, I guess-do-not-answer-the-question-with-a-question, (IF it is MEANT this way- IF NOT I do apologize!) – William Martens Feb 08 '22 at 07:57