我编写了一个 shell 脚本来使用 jq 读取 json 文件并编写该文件的漂亮版本:
cat input.json | jq . > pretty.json
cp pretty.json ./input.json
rm pretty.json
需要第 2 行和第 3 行是因为
cat input.json | jq . > input.json
文件留空,有没有办法使用 shell/jq 来美化文件而不使用临时文件?
答案1
不,您不能处理文件jq
并将结果输出到原始文件。
您可以像这样使用临时文件:
cp file.json file.json.tmp &&
jq . file.json.tmp >file.json &&
rm file.json.tmp
此操作顺序还保留原始文件的元数据。由于每个步骤都取决于上一步的成功完成(由于),因此如果运行失败&&
等情况,您将不会丢失文档。jq
sponge
您可以使用 GNU (软件包的一部分)等工具moreutils
来隐藏处理临时文件的体力劳动:
jq . file.json | sponge file.json
请注意,这仍然在幕后使用临时文件。
在这两个变体中,只有前一组三个命令可以在分区突然变满或jq
无法正常执行(由于不可用或输入文档中存在错误)时保护您免遭数据丢失。
答案2
json-beautify-inplace () {
temp=$(mktemp)
printf 'input = %s\n' "$1"
printf 'temp = %s\n' "$temp"
cp -- "$1" "$temp"
jq . "$temp" > "$1"
}
json-uglify-inplace () {
temp=$(mktemp)
printf 'input = %s\n' "$1"
printf 'temp = %s\n' "$temp"
cp -- "$1" "$temp"
jq -r tostring "$temp" > "$1"
}
答案3
确实可以将您的file.json
文件替换为其副本,并用 进行美化jq
,而无需使用临时文件,但这有点黑客:
( exec < file.json; rm file.json; jq . > file.json )
关于此命令行中“魔法”的一些解释:
exec < file.json
打开原始file.json
文件作为整个 shell 的标准输入,因此接下来的命令将将此文件作为其标准输入,rm file.json
取消链接文件以确保其内容不会被即将到来的命令覆盖,但只要文件保持打开状态,该内容仍然可用,jq . > file.json
将 JSON 从标准输入美化到新file.json
文件,- 整个命令行被括在括号中,以便在子 shell 中运行它,因此删除的文件将被关闭,并且标准输入将在最后恢复。
请注意,您可以用稍微更紧凑的方式编写它:
( rm file.json; jq . > file.json ) < file.json
无论如何,我建议使用临时文件而不是这样做!
答案4
由于jq
无法做到这一点,我在.bashrc
and中定义了这个 shell 函数.zshrc
:
prettify() {
local temp_file
temp_file=$(mktemp) &&
jq . < "$1" > "$temp_file" &&
mv -- "$temp_file" "$1"
}
prettify foo.json
现在做我需要的事情。