使用 Bash 编写 JSON 文件的最有效方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31254887/
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
What is the most efficient way of writing a JSON file with Bash?
提问by THIS USER NEEDS HELP
So I have to write a JSON file with bash script, and I know I can do something like echo 'something' >> $file
to slowly build a file, but echo redirection instead of real file output seems kind of "hacky." If that is the best way, and not a hacky way at all, I am happy to use echo,
but I was just wondering if there is a better way to output a file from bash script.
所以我必须用 bash 脚本编写一个 JSON 文件,我知道我可以做一些事情,比如echo 'something' >> $file
慢慢地构建一个文件,但是回显重定向而不是真正的文件输出似乎有点“hacky”。如果那是最好的方法,而不是一种很笨的方法,我很乐意使用,echo,
但我只是想知道是否有更好的方法来从 bash 脚本输出文件。
回答by Charles Duffy
Efficiently generating output
高效生成输出
echo
is a built-in, not an external command, so it's not nearly as inefficient as you think. What isinefficient is putting >> filename
on the end of each echo
.
echo
是一个内置命令,而不是外部命令,因此它的效率并不像您想象的那么低。什么是低效的是把>> filename
每个月底echo
。
This is bad:
这不好:
# EVIL!
echo "something" >file
echo "first line" >>file
echo "second line" >>file
This is good:
这很好:
# NOT EVIL!
{
echo "something" >&3
printf '%s\n' "first line" "$second line" >&3
# ... etc ...
} 3>file
...opens the output file only once, eliminating the major inefficiency.
...只打开输出文件一次,消除了主要的低效率。
To be clear: Calling echo
, say, 20 times is considerably more efficient than calling cat
once, since cat
is an external process, not part of the shell.What's highly inefficient about running echo "foo" >>file
20 times is opening and closing the output file 20 times; it's not echo
itself.
需要明确的是:例如,调用echo
20 次比调用cat
一次更有效,因为它cat
是一个外部进程,而不是外壳的一部分。运行echo "foo" >>file
20 次效率极低的是打开和关闭输出文件 20 次;它不是echo
它自己。
Correctly generating JSON
正确生成 JSON
Don't use cat
, echo
, printf
, or anything else of the sort. Instead, use a tool that understands JSON -- any other approach will lead to potentially incorrect (perhaps even exploitable via injection attacks) results.
不要使用cat
、echo
、printf
或任何其他类型的东西。相反,使用理解 JSON 的工具——任何其他方法都可能导致不正确的(甚至可能通过注入攻击利用)结果。
For instance:
例如:
jq \
--arg something "$some_value_here" \
--arg another "$another_value" \
'.["something"]=$something | .["another_value"]=$another' \
<template.json >output.json
...will generate a JSON file, based on template.json
, with something
set to the value in the shell variable "$some_value_here"
and another_value
set to, well, a second value. Unlike naive approaches, this will correctly handle variable values which contain literal quotes or other characters which need to be escaped to be correctly represented.
...会生成一个JSON文件的基础上template.json
,与something
设置为shell变量的值"$some_value_here"
,并another_value
设置为,那么,第二个值。与幼稚的方法不同,这将正确处理包含需要转义以正确表示的文字引号或其他字符的变量值。
An aside on echo
关于回声的旁白
All the above having been said -- echo
should be avoided in favor of printf
(with an appropriate, static format string). Per the POSIX sh standard:
上面所说的 -echo
应该避免使用printf
(使用适当的静态格式字符串)。根据 POSIX sh 标准:
APPLICATION USAGE
It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted.
The printf utility can be used portably to emulate any of the traditional behaviors of the echo utility as follows (assuming that IFS has its standard value or is unset):
[...]
New applications are encouraged to use printf instead of echo.
RATIONALE
The echo utility has not been made obsolescent because of its extremely widespread use in historical applications. Conforming applications that wish to do prompting without s or that could possibly be expecting to echo a -n, should use the printf utility derived from the Ninth Edition system.
As specified, echo writes its arguments in the simplest of ways. The two different historical versions of echo vary in fatally incompatible ways.
The BSD echo checks the first argument for the string -n which causes it to suppress the that would otherwise follow the final argument in the output.
The System V echo does not support any options, but allows escape sequences within its operands, as described for XSI implementations in the OPERANDS section.
The echo utility does not support Utility Syntax Guideline 10 because historical applications depend on echo to echo all of its arguments, except for the -n option in the BSD version.
应用用途
除非 -n(作为第一个参数)和转义序列都被省略,否则不可能在所有 POSIX 系统中便携地使用 echo。
printf 实用程序可移植地用于模拟 echo 实用程序的任何传统行为,如下所示(假设 IFS 具有其标准值或未设置):
[...]
鼓励新应用程序使用 printf 而不是 echo。
基本原理
echo 实用程序并没有因为它在历史应用中的广泛使用而过时。希望在没有 s 的情况下进行提示或可能期望回显 -n 的符合标准的应用程序应该使用从第九版系统派生的 printf 实用程序。
按照规定,echo 以最简单的方式写入其参数。回声的两个不同历史版本以致命的不相容方式不同。
BSD 回显检查字符串 -n 的第一个参数,这导致它抑制输出中的最后一个参数。
System V echo 不支持任何选项,但允许在其操作数中使用转义序列,如操作数部分中针对 XSI 实现的描述。
echo 实用程序不支持实用程序语法指南 10,因为历史应用程序依赖 echo 来回显其所有参数,但 BSD 版本中的 -n 选项除外。
回答by Mr. Llama
You can use cat
and here-document format:
您可以使用cat
和here-document 格式:
cat <<'EOF' > output.json
{
"key": "value",
"num": 5,
"tags": ["good", "bad"],
"money": "var=something
var="$var something else"
var="$var and another thing"
echo "$var" > file
"
}
EOF
Note the single ticks around the here-document anchor. This prevents interpolation of the document's contents. Without it, the $0
can be substituted.
请注意此处文档锚点周围的单个勾号。这可以防止插入文档内容。没有它,$0
可以替换。
If you define efficiency as raw speed as opposed to readability, you should consider using Charles Duffy's answer insteadas it's almost an order of magnitude faster for small number of lines (echo
0.01s vs cat
0.1s).
If you need to create files larger than a few hundred lines, you should consider a method other than cat
/echo
.
如果您将效率定义为原始速度而不是可读性,则您应该考虑使用Charles Duffy 的答案,因为对于少量行(echo
0.01s 与cat
0.1s),它几乎快了一个数量级。
如果您需要创建大于几百行的文件,则应考虑使用cat
/以外的方法echo
。
回答by mob
Construct the data in an environment variable, and echo it once.
在环境变量中构造数据,并回显一次。
cat > myfile << EOF
Hello
World
!
EOF
回答by Eugeniu Rosca
Besides echo
, you could use cat
:
此外echo
,您可以使用cat
:
$ cat foo.sh
cat <<'HERE' > output
This
that
the other
indentation is
preserved
as are
blank lines
The end.
HERE
$ sh foo.sh
$ cat output
This
that
the other
indentation is
preserved
as are
blank lines
The end.
回答by Andy Lester
You can use cat
and "heredocs" to minimize the number of calls you have to make.
您可以使用cat
和“heredocs”来最小化您必须拨打的电话数量。