bash 中的转义字符(对于 JSON)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10053678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Escaping characters in bash (for JSON)
提问by Rich Bradshaw
I'm using git, then posting the commit message and other bits as a JSON payload to a server.
我正在使用 git,然后将提交消息和其他位作为 JSON 有效负载发布到服务器。
Currently I have:
目前我有:
MSG=`git log -n 1 --format=oneline | grep -o ' .\+'`
which sets MSG to something like:
它将 MSG 设置为类似:
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.
我真正的 JSON 有另外几个字段。
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.
这工作正常,但当然,当我有一个提交消息时,例如上面带有撇号的消息,JSON 无效。
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.
如何转义 bash 中所需的字符?我不熟悉这门语言,所以不知道从哪里开始。替换'with\'至少可以完成我怀疑的工作。
采纳答案by Rich Bradshaw
OK, found out what to do. Bash supports this natively as expected, though as always, the syntax isn't really very guessable!
好的,知道该怎么做了。Bash 按预期在本机支持此功能,尽管与往常一样,语法并不是很容易猜测!
Essentially ${string//substring/replacement}returns what you'd image, so you can use
基本上${string//substring/replacement}返回你想要的图像,所以你可以使用
MSG=${MSG//\'/\\'}
To do this. The next problem is that the first regex doesn't work anymore, but that can be replaced with
去做这个。下一个问题是第一个正则表达式不再起作用,但可以用
git log -n 1 --pretty=format:'%s'
In the end, I didn't even need to escape them. Instead, I just swapped all the ' in the JSON to \". Well, you learn something every day.
最后,我什至不需要逃避他们。相反,我只是将 JSON 中的所有 ' 交换为 \"。好吧,您每天都会学到一些东西。
回答by polm23
Using Python:
使用 Python:
This solution is not pure bash, but it's non-invasive and handles unicode.
这个解决方案不是纯粹的 bash,但它是非侵入性的并且处理 unicode。
json_escape () {
printf '%s' "" | 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.
请注意,JSON 是标准 python 库的一部分,并且已经存在很长时间了,因此这是一个非常小的 python 依赖项。
Or using PHP:
或者使用 PHP:
json_escape () {
printf '%s' "" | php -r 'echo json_encode(file_get_contents("php://stdin"));'
}
Use like so:
像这样使用:
$ json_escape "ヤホー"
"\u30e4\u30db\u30fc"
回答by chepner
Instead of worrying about how to properly quote the data, just save it to a file and use the @construct that curlallows with the --dataoption. To ensure that the output of gitis correctly escaped for use as a JSON value, use a tool like jqto generate the JSON, instead of creating it manually.
无需担心如何正确引用数据,只需将其保存到文件中并使用该选项允许的@结构即可。为确保正确转义的输出以用作 JSON 值,请使用类似生成 JSON的工具,而不是手动创建它。curl--datagitjq
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'
You can also read directly from standard input using -d @-; I leave that as an exercise for the reader to construct the pipeline that reads from gitand produces the correct payload message to upload with curl.
您还可以使用-d @-;直接从标准输入中读取。我将它作为一个练习留给读者来构造管道,它读出git并产生正确的有效载荷消息上传curl。
(Hint: it's jq ... | curl ... -d@- 'https://example.com')
(提示:是jq ... | curl ... -d@- 'https://example.com')
回答by jchook
jqcan do this.
jq可以做到这一点。
Lightweight, free, and written in C, jqenjoys widespread community support with over 15k stars on GitHub. I personally find it very speedy and useful in my daily workflow.
轻量级、免费、用 C 语言编写,jq在GitHub 上获得了超过 15,000 颗星的广泛社区支持。我个人认为它在我的日常工作流程中非常快速和有用。
Convert string to JSON
将字符串转换为 JSON
jq -aRs . <<< '猫に小判'
To explain,
解释,
-ameans "ascii output"-Rmeans "raw input"-smeans "include linebreaks".means "output the root of the JSON document"<<<passes a string into stdin (bash only?)
-a意思是“ascii 输出”-R意思是“原始输入”-s意思是“包括换行符”.意思是“输出 JSON 文档的根”<<<将字符串传递到标准输入中(仅限 bash?)
Git + Grep Use Case
Git + Grep 用例
To fix the code example given by the OP, simply pipe through jq.
要修复 OP 给出的代码示例,只需通过 jq 管道即可。
MSG=`git log -n 1 --format=oneline | grep -o ' .\+' | jq -aRs .`
回答by xsgordon
I was also trying to escape characters in Bash, for transfer using JSON, when I came across this. I found that there is actually a larger list of characters that must be escaped– particularly if you are trying to handle free form text.
当我遇到这个时,我也试图在 Bash 中转义字符,以便使用 JSON 进行传输。我发现实际上有一个更大的字符列表必须被转义——特别是如果你试图处理自由格式的文本。
There are two tips I found useful:
我发现有两个提示很有用:
- Use the Bash
${string//substring/replacement}syntax described in this thread. - Use the actual control characters for tab, newline, carriage return, etc. In vim you can enter these by typing Ctrl+Vfollowed by the actual control code (Ctrl+Ifor tab for example).
- 使用
${string//substring/replacement}此线程中描述的 Bash语法。 - 将实际控制字符用于制表符、换行符、回车等。在 vim 中,您可以通过键入Ctrl+V后跟实际控制代码来输入这些字符(例如,Ctrl+I表示制表符)。
The resultant Bash replacements I came up with are as follows:
我想出的 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)
I have not at this stage worked out how to escape Unicode characters correctly which is also (apparently) required. I will update my answer if I work this out.
在这个阶段,我还没有弄清楚如何正确转义 Unicode 字符,这也是(显然)需要的。如果我解决了这个问题,我会更新我的答案。
回答by wcy
git log -n 1 --format=oneline | grep -o ' .\+' | jq --slurp --raw-input
The above line works for me. refer to
https://github.com/stedolan/jqfor more jqtools
上面的行对我有用。更多工具请参考
https://github.com/stedolan/jqjq
回答by m-szalik
回答by user907860
I found something like that :
我发现了类似的东西:
MSG=`echo $MSG | sed "s/'/\\\'/g"`
回答by KirillDE
I had the same idea to send a message with commit message after commit. First i tryed similar was as autor here. But later found a better and simpler solution.
我有同样的想法在提交后发送带有提交消息的消息。首先,我在这里尝试过类似的作者。但是后来找到了一个更好更简单的解决方案。
Just created php file which is sending message and call it with wget. in hooks/post-receive :
刚刚创建的 php 文件正在发送消息并用 wget 调用它。在钩子/接收后:
wget -qO - "http://localhost/git.php"
in git.php:
在 git.php 中:
chdir("/opt/git/project.git");
$git_log = exec("git log -n 1 --format=oneline | grep -o ' .\+'");
And then create JSON and call CURL in PHP style
然后创建JSON并以PHP风格调用CURL
回答by Josh Bode
This is an escaping solution using Perl that escapes backslash (\), double-quote (") and control characters U+0000to U+001F:
这是使用 Perl 的转义解决方案,可将反斜杠 ( \)、双引号 ( ") 和控制字符转义U+0000为U+001F:
$ echo -ne "Hello, \n\tBye" | \
perl -pe 's/(\(\\)*)//g; s/(?!\)(["\x00-\x1f])/sprintf("\u%04x",ord())/eg;'
Hello, \u000a\u0009Bye

