How to pass a string with spaces to a command which returns itself a string with spaces?
I tried the following four versions.
arg='one arg'
arg() { echo "arg: $1"; }
printf '1 |%s|\n' $(arg "$arg")
printf '2 |%s|\n' "$(arg $arg)"
printf '3 |%s|\n' "$(arg \"$arg\")"
printf '4 |%s|\n' "$(arg '$arg')"
They all fail:
1 |arg:| 1 |one| 1 |arg| 2 |arg: one| 3 |arg: "one| 4 |arg: $arg|
How to get this result?
? |arg: one arg|
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|
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With