所以我必须用bash脚本编写一个JSON文件,我知道我可以做echo 'something' >> $file
之类的东西来慢慢构建一个文件,但回显重定向而不是真正的文件输出似乎有点" hacky "如果这是最好的方式,而不是一种hacky方式,我很高兴使用echo,
,但我只是想知道是否有更好的方法从bash脚本输出文件。
答案 0 :(得分:11)
echo
是一个内置命令,而不是外部命令,所以它并不像你想象的那么低效。 效率低下的原因是将>> filename
放在每个echo
的末尾。
这很糟糕:
# EVIL!
echo "something" >file
echo "first line" >>file
echo "second line" >>file
这很好:
# NOT EVIL!
{
echo "something" >&3
printf '%s\n' "first line" "$second line" >&3
# ... etc ...
} 3>file
...只打开一次输出文件,消除了主要的低效率。
要明确:调用echo
,比如20次,比调用cat
一次效率要高得多,因为cat
是一个外部进程,而不是shell的一部分运行echo "foo" >>file
20次非常低效的是打开和关闭输出文件20次;它不是echo
本身。
请勿使用cat
,echo
,printf
或其他类似内容。相反,使用了解JSON的工具 - 任何其他方法都可能导致潜在的错误(甚至可能是可利用的注入攻击)结果。
例如:
jq \
--arg something "$some_value_here" \
--arg another "$another_value" \
'.["something"]=$something | .["another_value"]=$another' \
<template.json >output.json
...将根据template.json
生成一个JSON文件,something
设置为shell变量"$some_value_here"
中的值,another_value
设置为,{第二个值。与朴素方法不同,这将正确处理包含文字引号或其他需要转义以正确表示的字符的变量值。
上述所有内容 - echo
应该避免使用printf
(使用适当的静态格式字符串)。 Per the POSIX sh standard:
申请使用
除非省略-n(作为第一个参数)和转义序列,否则无法在所有POSIX系统中使用echo。
printf实用程序可以移植来模拟echo实用程序的任何传统行为,如下所示(假设IFS具有其标准值或未设置):
[...]
鼓励新应用程序使用printf而不是echo。
基本原理
回声实用程序由于在历史应用程序中的广泛使用而未被淘汰。符合希望在没有s的情况下进行提示或者可能期望回显-n的应用程序应该使用从第九版系统派生的printf实用程序。
如上所述,echo以最简单的方式写入其参数。回声的两种不同的历史版本以致命的不相容方式变化。
BSD echo检查字符串-n的第一个参数,这会导致它抑制输出中的最后一个参数。
System V echo不支持任何选项,但允许其操作数内的转义序列,如OPERANDS部分中的XSI实现所述。
echo实用程序不支持实用程序语法准则10,因为历史应用程序依赖于echo来回显其所有参数,但BSD版本中的-n选项除外。
答案 1 :(得分:6)
您可以使用cat
和here-document format:
cat <<'EOF' > output.json
{
"key": "value",
"num": 5,
"tags": ["good", "bad"],
"money": "$0"
}
EOF
请注意here-document锚点周围的单个刻度。这可以防止插入文档的内容。没有它,$0
可以替代。
如果您将效率定义为原始速度而不是可读性,则应考虑使用Charles Duffy's answer instead,因为对于少量行(echo
0.01s vs {{1},它几乎快一个数量级} 0.1s)。
如果您需要创建大于几百行的文件,则应考虑cat
/ cat
以外的方法。
答案 2 :(得分:3)
在环境变量中构造数据,并回显一次。
var=something
var="$var something else"
var="$var and another thing"
echo "$var" > file
答案 3 :(得分:1)
除了echo
,您可以使用cat
:
cat > myfile << EOF
Hello
World
!
EOF
答案 4 :(得分:0)
您可以使用cat
和“heredocs”来减少您必须拨打的电话数量。
$ 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.