Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Escaping characters in bash (for JSON)

I'm using git, then posting the commit message and other bits as a JSON payload to a server.

Currently I have:

MSG=`git log -n 1 --format=oneline | grep -o ' .\+'` 

which sets MSG to something like:

Calendar can't go back past today 

then

curl -i -X POST \   -H 'Accept: application/text' \   -H 'Content-type: application/json' \   -d "{'payload': {'message': '$MSG'}}" \   'https://example.com' 

My real JSON has another couple of fields.

This works fine, but of course when I have a commit message such as the one above with an apostrophe in it, the JSON is invalid.

How can I escape the characters required in bash? I'm not familiar with the language, so am not sure where to start. Replacing ' with \' would do the job at minimum I suspect.

like image 733
Rich Bradshaw Avatar asked Apr 07 '12 10:04

Rich Bradshaw


People also ask

How do you escape special characters in Bash?

3.1. 2.1 Escape CharacterA non-quoted backslash ' \ ' is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline .

How do you escape a forward slash in JSON?

JSON escapes the forward slash, so a hash {a: "a/b/c"} is serialized as {"a":"a\/b\/c"} instead of {"a":"a/b/c"} .

How do you escape a string in Bash?

To escape a string for use as a command line argument in Bash, simply put a backslash in front of every non-alphanumeric character. Do not wrap the string in single quotes or double quotes.


2 Answers

jq can do this.

Lightweight, free, and written in C, jq enjoys widespread community support with over 15k stars on GitHub. I personally find it very speedy and useful in my daily workflow.

Convert string to JSON

$ echo '猫に小判' | jq -aRs . "\u732b\u306b\u5c0f\u5224\n" 
$ printf 'ô\nè\nà\n' | jq -Rs . "ô\nè\nà\n" 

To explain,

  • -a means "ascii output" (omitted in the second example)
  • -R means "raw input"
  • -s means "include linebreaks" (mnemonic: "slurp")
  • . means "output the root of the JSON document"

Git + Grep Use Case

To fix the code example given by the OP, simply pipe through jq.

MSG=`git log -n 1 --format=oneline | grep -o ' .\+' | jq -aRs .` 
like image 163
jchook Avatar answered Sep 22 '22 23:09

jchook


Using Python:

This solution is not pure bash, but it's non-invasive and handles unicode.

json_escape () {     printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))' } 

Note that JSON is part of the standard python libraries and has been for a long time, so this is a pretty minimal python dependency.

Or using PHP:

json_escape () {     printf '%s' "$1" | php -r 'echo json_encode(file_get_contents("php://stdin"));' } 

Use like so:

$ json_escape "ヤホー" "\u30e4\u30db\u30fc" 
like image 23
polm23 Avatar answered Sep 21 '22 23:09

polm23