I have an interesting challenge for how to escape quotes in a bash script.

My bash script has a long curl call with a large -d json structure passed.



curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d  \
"Variable2":"Value2\'s",  # escape of quote doesnt work because of the previous single quote and backslash
}' \

What's the best way to add a single quote into the json structure? I've tried various combinations but no success.

  • 2
    The same way you used for expanding the variable. End the single-quotes, insert a single-quote (either quoted or escaped), then start the single-quoted string again. So '....'\''....' or '....'"'"'....' – ilkkachu Jan 3 '18 at 18:30
  • 1
    Why not put the JSON into a data file, and use curl [...] --data @mydata.json? – DopeGhoti Jan 3 '18 at 18:42
  • 1
    @DopeGhoti there is a variable that needs to be expanded inside the json - it won't be expanded inside a file without extra work. – Michael Daffin Jan 3 '18 at 18:50

There are multiple ways to escape long strings with different quotes. The simplest is to end the single quote and escape the single quote:


But there are some nicer things you can do. Heredocs are a good way to avoid the quoting issue:

curl -s -X POST https://www.hashemian.com/tools/form-post-tester.php \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -d  @- <<EOF

@- tell curl to read from stdin and <<EOF starts the heredoc which will be feed into the stdin of curl. The nice thing with the heredoc is that you do not need to escape any quotes and can use bash variables inside them sidestepping the need to worry about how to escape the quotes and making the whole thing much more readable.

  • Thanks. The EOF is a really nice approach. I've used it before with ftp commands but I didn't strike the connection that I can use it in curl too. – Bernie Lenz Jan 3 '18 at 23:00

I would use --data @filename notation to read the data from file:

Sample json-data-file contents:


The request:

curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" \
-d @<(sed "s/\$Value4Variable/$Value4Variable/" json-data-file) \

The output:

The POSTed value is:


{"Variable1":"Value1", "Variable2":"Value2's","Variable3":"Value3","Variable4":"'Value4'", "Variable5":"Value5"}


Results saved to: test123
*Note: Results are purged periodically. 1 hr minimum life.
  • Thanks! This works although I prefer to have it all in one file as there are multiple curls in the script and splitting them all into different files makes maintenance a bit more convoluted. – Bernie Lenz Jan 3 '18 at 22:57

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.