我可以使用 jq 来美化文件吗?

我可以使用 jq 来美化文件吗?

我编写了一个 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无法做到这一点,我在.bashrcand中定义了这个 shell 函数.zshrc

prettify() {
    local temp_file
    temp_file=$(mktemp) &&
      jq . < "$1" > "$temp_file" &&
      mv -- "$temp_file" "$1"
}

prettify foo.json现在做我需要的事情。

相关内容