我使用git,然后将提交消息和其他位作为JSON有效负载发布到服务器。
目前我有:
MSG=`git log -n 1 --format=oneline | grep -o ' .\+'`
将MSG设置为:
Calendar can't go back past today
然后
curl -i -X POST \
-H 'Accept: application/text' \
-H 'Content-type: application/json' \
-d "{'payload': {'message': '$MSG'}}" \
'https://example.com'
我真正的JSON有另外两个领域。
这样可以正常工作,但是当我有一个提交消息(如上面的撇号)时,JSON无效。
如何逃避bash中所需的字符?我不熟悉这种语言,所以不知道从哪里开始。用'
替换\'
至少可以做到我怀疑的工作。
答案 0 :(得分:52)
使用Python:
这个解决方案不是纯粹的bash,但它是非侵入性的并处理unicode。
json_escape () {
printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))'
}
请注意,JSON是标准python库的一部分并且已经存在了很长时间,因此这是一个非常小的python依赖项。
或使用PHP:
json_escape () {
printf '%s' "$1" | php -r 'echo json_encode(file_get_contents("php://stdin"));'
}
像这样使用:
$ json_escape "ヤホー"
"\u30e4\u30db\u30fc"
答案 1 :(得分:39)
不要担心如何正确引用数据,只需将其保存到文件中,然后使用@
允许的curl
结构--data
选项。要确保正确转义git
的输出以用作JSON值,请使用jq
之类的工具生成JSON,而不是手动创建。
jq -n --arg msg "$(git log -n 1 --format=oneline | grep -o ' .\+')" \
'{payload: { message: $msg }}' > git-tmp.txt
curl -i -X POST \
-H 'Accept: application/text' \
-H 'Content-type: application/json' \
-d @git-tmp.txt \
'https://example.com'
您还可以使用-d @-
直接从标准输入中读取;我将此作为练习让读者构建从git
读取的管道,并生成正确的有效负载消息以上传curl
。
(提示:它是jq ... | curl ... -d@- 'https://example.com'
)
答案 2 :(得分:16)
当我遇到这个时,我还试图在Bash中转义字符,以便使用JSON进行转移。我发现实际上有更大的list of characters that must be escaped - 特别是如果您正在尝试处理自由格式文本。
我发现有两个有用的提示:
${string//substring/replacement}
语法。我想出的最终Bash替换如下:
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//\\/\\\\} # \
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//\//\\\/} # /
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//\'/\\\'} # ' (not strictly needed ?)
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//\"/\\\"} # "
JSON_TOPIC_RAW=${JSON_TOPIC_RAW// /\\t} # \t (tab)
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//
/\\\n} # \n (newline)
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//^M/\\\r} # \r (carriage return)
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//^L/\\\f} # \f (form feed)
JSON_TOPIC_RAW=${JSON_TOPIC_RAW//^H/\\\b} # \b (backspace)
我还没有在这个阶段弄清楚如何正确地转义Unicode字符,这也是(显然)需要的。如果我解决这个问题,我会更新我的答案。
答案 3 :(得分:11)
好的,找到了该怎么做。 Bash正如预期的那样本地支持它,虽然一如既往,语法并不是真的可以猜测!
基本上${string//substring/replacement}
会返回您要成像的内容,因此您可以使用
MSG=${MSG//\'/\\\'}
要做到这一点。下一个问题是第一个正则表达式不再起作用,但可以用
替换git log -n 1 --pretty=format:'%s'
最后,我甚至不需要逃避它们。相反,我只是把JSON中的所有'换成了'。嗯,你每天都学到一些东西。
答案 4 :(得分:11)
jq
可以做到这一点。
轻量级,免费且用C语言编写,jq
享有广泛的社区支持,GitHub上有超过12.5k的星星。我个人觉得它在我的日常工作流程中非常快速有用。
jq -aR . <<< '猫に小判'
解释,
-a
表示“ascii output”-R
表示“原始输入”.
表示“输出JSON文档的根目录”<<<
将字符串传递给stdin(仅限bash?)要修复OP给出的代码示例,只需通过jq。
MSG=`git log -n 1 --format=oneline | grep -o ' .\+' | jq -aR .`
答案 5 :(得分:6)
git log -n 1 --format=oneline | grep -o ' .\+' | jq --slurp --raw-input
以上这条线适合我。参考
https://github.com/stedolan/jq了解更多jq
工具
答案 6 :(得分:4)
我找到了类似的东西:
MSG=`echo $MSG | sed "s/'/\\\\\'/g"`
答案 7 :(得分:4)
最简单的方法是使用jshon,一个命令行工具来解析,读取和创建JSON 。
jshon -s 'Your data goes here.' 2>/dev/null
答案 8 :(得分:0)
我有同样的想法在提交后发送带有提交消息的消息。 首先我尝试类似的是在这里作为autor。 但后来发现了一种更好,更简单的解决方案。
刚刚创建的php文件正在发送消息并用wget调用它。 in hooks / post-receive:
wget -qO - "http://localhost/git.php"
在git.php中:
chdir("/opt/git/project.git");
$git_log = exec("git log -n 1 --format=oneline | grep -o ' .\+'");
然后创建JSON并以PHP样式调用CURL
答案 9 :(得分:0)
这是一个使用Perl的转义解决方案,它将反斜杠(\
),双引号("
)和控制字符U+0000
转义为U+001F
:
$ echo -ne "Hello, \n\tBye" | \
perl -pe 's/(\\(\\\\)*)/$1$1/g; s/(?!\\)(["\x00-\x1f])/sprintf("\\u%04x",ord($1))/eg;'
Hello, \u000a\u0009Bye
答案 10 :(得分:0)
我也遇到同样的问题。我试图在bash中的cURL的有效负载上添加一个变量,并且该变量一直以invalid_JSON的形式返回。在尝试了许多逃避技巧之后,我找到了解决问题的简单方法。答案全部在单引号和双引号中:
curl --location --request POST 'https://hooks.slack.com/services/test-slack-hook' \
--header 'Content-Type: application/json' \
--data-raw '{"text":'"$data"'}'
也许对某人来说很方便!
答案 11 :(得分:0)
[...]中带有撇号,则JSON无效。
不符合https://www.json.org。 JSON字符串中允许使用单引号。
如何转义bash中所需的字符?
不是必需的。一切都与引号有关。
由于您没有明确标记这个问题curl,因此我的回答中也会包含xidel
。就像curl
和jq
一样。
由于无法测试https://example.com
,因此我将使用https://api.github.com/markdown
(请参阅this答案)。
$ msg=$(git log -n 1 --pretty=format:'%s')
$ curl -d '{"text":"'"$msg"'"}' https://api.github.com/markdown
$ curl -d "{\"text\":\"$msg\"}" https://api.github.com/markdown
$ xidel -s -d '{{"text":"'"$msg"'"}}' https://api.github.com/markdown -e '$raw'
$ xidel -s -d "{{\"text\":\"$msg\"}}" https://api.github.com/markdown -e '$raw'
$ xidel -s -e '
x:request({
"post":serialize-json({"text":"'"$msg"'"}),
"url":"https://api.github.com/markdown"
})/raw
'
$ curl -d '{"text":"'"$(git log -n 1 --pretty=format:'%s')"'"}' https://api.github.com/markdown
$ curl -d "{\"text\":\"$(git log -n 1 --pretty=format:'%s')\"}" https://api.github.com/markdown
$ xidel -s -d '{{"text":"'"$(git log -n 1 --pretty=format:'%s')"'"}}' https://api.github.com/markdown -e '$raw'
$ xidel -s -d "{{\"text\":\"$(git log -n 1 --pretty=format:'%s')\"}}" https://api.github.com/markdown -e '$raw'
$ xidel -s -e '
x:request({
"post":serialize-json({"text":"'"$(git log -n 1 --pretty=format:'%s')"'"}),
"url":"https://api.github.com/markdown"
})/raw
'
$ git log -n 1 --pretty=format:'%s' | xidel -s -d '{{"text":"{read()}"}}' https://api.github.com/markdown -e '$raw'
$ git log -n 1 --pretty=format:'%s' | xidel -s -d "{{\"text\":\"{read()}\"}}" https://api.github.com/markdown -e '$raw'
$ git log -n 1 --pretty=format:'%s' | xidel -s -e '
x:request({
"post":serialize-json({"text":read()}),
"url":"https://api.github.com/markdown"
})/raw
'
(也许curl
也有可能,但我还没有找到方法)
所有13条命令应返回:<p>Calendar can't go back past today</p>