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.
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 .
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"} .
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.
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.
$ 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"To fix the code example given by the OP, simply pipe through jq.
MSG=`git log -n 1 --format=oneline | grep -o ' .\+' | jq -aRs .`
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"
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