0

I have an obvious problem with quoting in bash such that I couldn't really solve for a while. Here is a loop with executing a remote command in a sudo-subshell on a remote server via ssh:

for HOST in $RUNNER_LIST; do
  ssh -t $HOST "sudo bash -c \"sed -i '$a 10.10.40.29 myhost' /etc/hosts\""
done 2>/dev/null

Now, this simple approach, of course, doesn't work. That $a gets expanded by the local shell, and since that's an unset variable sed executes the expression ' 10.10.40.29 myhost'

I've tried out several approaches, and during writing this question, I somehow found out that this worked:

ssh -t $HOST "sudo bash -c \"sed -i '"'\$'"a 10.10.40.29 myhost' /etc/hosts\""

and using prepended set -x, I see that on the remote shell, it's expanded to

sudo bash -c 'sed '\''$a 10.10.40.29 myhost'\'' /etc/hosts'

I was surprised since my intention was to escape $. Instead of it, the quotes got escaped. So I would like to have a clear explanation of how this expansion worked. And maybe there is a way to make this command more readable?

1 Answers1

0

This does not really answer your question (I did read your post too quickly, sorry); To properly do what you wanted, you need to doubly escape the $ (for sed, and for bash) :

for HOST in $RUNNER_LIST; do
  ssh -t $HOST "sudo bash -c \"sed -i '\\\$a 10.10.40.29 myhost' /tmp/hosts\""
done 2>/dev/null

Without the bash -c, only one level is necessary :

for HOST in $RUNNER_LIST; do
  ssh -t $HOST "sudo sed -i '\$a 10.10.40.29 myhost' /tmp/hosts"
done 2>/dev/null
Bruno
  • 180