【问题标题】:JQ Split JSON in several filesJQ 在几个文件中拆分 JSON
【发布时间】:2022-01-03 18:02:15
【问题描述】:

我是新手。并尝试根据内容将 JSON 保留或拆分为多个文件。 目标组的“名称”是“root_rgs”,我希望将其分别放在不同的文件中。

{
  "root_rgs": [
    "PROM_FD_ARCNA",
    "PROM_JOB_ICMP"
  ],
  "targets": [
    "HCC02155",
    "HCC09350",
    "HCC09321",
    "HCCEFACTORYWWW",
    "HCC9723"
  ]
}
{
  "root_rgs": [
    "PROM_FD_ARCNA",
    "PROM_JOB_WIN"
  ],
  "targets": [
    "LABTNSARWID236",
    "LABTNSARWID692",
    "VM00006"
  ]
}
{
  "root_rgs": [
    "PROM_FD_MTZ",
    "PROM_JOB_ICMP"
  ],
  "targets": [
    "TEIARWIN205",
    "TEIARWDB150",
    "TEIARWCXWA212"
  ]
}

是否可以生成类似的东西:

ARCNA_ICMP.json

{
TARGETS:
        "HCC02155",
        "HCC09350",
        "HCC09321",
        "HCCEFACTORYWWW",
        "HCC9723"
}

ARCNA_WIN.json

{
TARGETS:
    "LABTNSARWID236",
    "LABTNSARWID692",
    "VM00006"
}

等等……

希望清楚,谢谢大家!

【问题讨论】:

  • Re "Hope to be clear",首先为您的预期输出提供有效的 JSON。你说你想要 JSON 输出,但提供的东西甚至不接近有效的 JSON。

标签: json file jq partition


【解决方案1】:

另一种可能性是将一次 jq 调用与一次像 awk 这样的实用程序调用结合起来编写文件:

jq -cr '(.root_rgs | "\(.[0]|sub("PROM_FD_";""))\(.[1]|sub("PROM_JOB";""))"),
        {TARGETS: .targets}' input.json |
  awk 'NR%2==1 {fn = $1 ".json"; next} {print $0 >> fn}'

当然,生成的文件通常不会打印得很漂亮。

警告:以上内容附加到现有文件中。实际上,处理此类文件的替代方法可能更可取。

【讨论】:

    【解决方案2】:

    jq 本身不能写入文件,既不能写入一个文件,也不能写入多个文件。然而,调用 jq 的 shell 可以。因此,任何解决方案都需要通过将任务拆分为多个部分来协调这两个级别,并由两个级别之一(或任何第三方工具)执行。

    一种直接的方法是使用 jq 将流分离为文档,并准备它们已经携带文件的名称和内容,并在 shell 中迭代该输出。然后,在每个迭代步骤中,都可以再次使用 jq 来提取该数据并让 shell 将内容保存到一个文件中。

    jq -c '{
      name: "\(.root_rgs | map(split("_")[-1]) | join("_")).json",
      content: {targets}
    }' input.json | while read -r json; do
      jq '.content' <<< "$json" > "$(jq -r '.name' <<< "$json")"
    done
    

    另一种方法是让 jq 生成一个可在 shell 中执行的脚本。这会将 jq 必须被调用的次数从 2n+1 减少到仅 1,如果输入文件包含许多文档,这可能很重要。

    jq -r '"cat"
      + " >\(.root_rgs | map(split("_")[-1]) | join("_")).json"
      + " <<<\({targets} | tojson | @sh)"
    ' input.json | bash
    

    这会为输入流中的每个文档生成一行 cat &gt;FILENAME &lt;&lt;&lt;'JSON' 形式的行,该行指示 shell 将 cat 发送到其输入的文件,而该文件又以 Here String 的形式提供,@987654326 可以理解@,命令最终通过管道传送到它。

    【讨论】: