In one word:

question and example could test locally:

sh -c "echo 'how to print single quote here'"


I have a config like this:

upload_server = ('', 10051)

now I need a shell script to replace server config. Locally I can do it with sed:

sed -E 's/(    upload_server = ).*/\\1('\"'$a'\"', 10051)/g' config.py

but there's huge amount of machines have to change the config.

a proper plan is to use ssh with for..in:

for i in `cat hosts`; do ssh $i "cmd"; done

but to change config also need a sudo, it looks like this:

for i in `cat hosts`; do ssh $i "sudo -c \"cmd\""; done

and now within sed:

cmd="sed -E 's/(    upload_server = ).*/\\1('\"\"'\"'${upload_server}'\"'\"\"', ${upload_server_port})/g' config.py"
ssh $i "sudo -c \"${cmd}\""

the result of config:

upload_server = (, 1000)

which should be like this:

upload_server = ('', 1000)

Now I'm confused a lot in quotes usage. :(

  • 1
    sudo -c? Why not just sudo cmd? – muru Jan 17 '17 at 4:17
  • this can help do a reduction of quotes, but there is still problem... – jixiang Jan 17 '17 at 4:55
  • 3
    Even someone who would feel comfortable in escaping them properly would chose not to do it that way because it is too confusing for nothing. Why don't you write a nice little script and scp it to the target before running it? That is much simpler, clearer, and adaptable. – Julie Pelletier Jan 17 '17 at 5:40
  • @JuliePelletier Yes, this is a simplest way. But a one-line-script looks the same as hold a candle to the sun. – jixiang Jan 17 '17 at 7:02
  • What's about if you write your upload_server without quotes? upload_server = (, 10051). Anyway, for your purpose, I think that it will be easier for you to use some automation tool like ansible (github.com/ansible/ansible) – Zumo de Vidrio Jan 17 '17 at 7:59

In this case, you can bypass the quoting issue entirely by passing the sed script on standard input. SSH routes the local standard input to the remote process, sudo just leaves it open, and sed can read its script on stdin. You can pass content for stdin with a here document.

for i in `cat hosts`; do
  ssh "$i" 'sudo sed -f - …' <<'EOF'
s/(    upload_server = ).*/\1("$a", 10051)/g

More generally, you can pass a shell snippet on stdin through SSH without worrying about quoting, as long as you don't need to also pass data on stdin.

for i in `cat hosts`; do
  ssh "$i" sudo sh <<'EOF'
sed 's/(    upload_server = ).*/\1("$a", 10051)/g' …

It isn't clear from your question whether you intended to insert "$a" into the configuration file, or "something" where the value of the variable a in the local shell is something. If you want to refer to the local variable, then use a here document with interpolation, and protect $\` in the here document with backslashes. Note that due to the parsing by sed, and by the remote shell in the second snippet, the value of the variable must not contain any of the characters \/' or a newline.

  ssh "$i" sudo sh <<EOF
sed 's/(    upload_server = ).*/\\1("$a", 10051)/g' …
  • quotes works well, but $a cannot be interpreted... – jixiang Jan 19 '17 at 3:32
  • @jixiang Did you mean $a to insert dollar-a in the configuration file, or to insert the content of the variable a defined in the shell on the local machine? This wasn't clear from your question. If you want to refer to the local variable (unlike the code snippet in your question), then you need to use a here document with interpolation. – Gilles Jan 19 '17 at 12:35
$ ssh localhost sh -c \"echo \\\'how to print single quotes here\\\'\"
'how to print single quotes here'

$ ssh localhost echo \\\'how to print single quotes here\\\'
'how to print single quotes here'

To understand the rules, remember that one level of quoting is stripped by the local shell, then SSH invokes a remote shell which strips a second level of quoting.

  • Thanks for your answer, but your answer maybe a misconception of my question. I mean inner the echo '', with an ' output. which echo is in "" . look my details for understand why I'm doing this. – jixiang Jan 18 '17 at 15:22
  • @jixiang: ssh localhost sh -c "\"echo \'how to print single quotes here\'\"". You need doublequotes around echo ... because sh -c expects the command to be one single argument. – AlexP Jan 18 '17 at 16:28
  • :) test pass on echo.... but on sed still not work.....very complicated.... – jixiang Jan 19 '17 at 3:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.