【问题标题】:Convert a flat JSON to a TSV file with column headers将平面 JSON 转换为带有列标题的 TSV 文件
【发布时间】:2020-12-01 17:31:52
【问题描述】:

我正在将一些带有 JQ 的 JSON 重新格式化为 TSV 文件。我可以仅使用值创建 TSV,但我无法弄清楚如何将单行包含键值作为列标题?

示例输入:

{
"id":"1234",
"host":"6789",
"proto":"UDP",
"location":"Boston",
"timestamp":"2020-12-01T14:18:45.717Z",
"src_ip":"192.168.3.70",
"dest_ip":"8.8.8.8",
"dest_port":53,
"message":"Some Information",
"severity":1,
"details":"Some Details",
"categories":["a","b","c"]
}

期望的输出:

"location\ttimestamp\tsrc_ip\tdest_ip\tdest_port"
"Boston\t2020-12-01T15:13:16.242Z\t10.8.25.63\t10.8.1.3\t445"
"Atlanta\t2020-12-01T15:11:15.929Z\t10.8.25.63\t10.80.1.3\t445"
"Chicago\t2020-12-01T15:09:45.271Z\t10.34.196.12\t10.8.1.3\t445"

这句话让我很接近:

cat input.json | jq  '. | to_entries 
| map(select(.key=="timestamp"), select(.key=="location"), select(.key=="src_ip"), select(.key=="dest_ip"), select(.key=="dest_port"))
| map(.key), map(.value) 
| @tsv'

但标题行在输出中重复:

"location\ttimestamp\tsrc_ip\tdest_ip\tdest_port"
"Boston\t2020-12-01T15:13:16.242Z\t10.8.25.63\t10.8.1.3\t445"
"location\ttimestamp\tsrc_ip\tdest_ip\tdest_port"
"Atlanta\t2020-12-01T15:11:15.929Z\t10.8.25.63\t10.80.1.3\t445"

有没有办法只打印第一行的键,然后只打印剩余行的值,只使用 JQ?

【问题讨论】:

标签: json jq


【解决方案1】:

使用@tsv 函数将这种平面对象 JSON 转换为 TSV 格式的一种方法是:

jq -n ' ["location", "timestamp", "src_ip", "dest_ip", "dest_port"] as $hdr | 
        $hdr, ( inputs | [ .[ $hdr[] ] ] ) | @tsv'

通过重用标题中的键字段,.[ $hdr[] ] 是一个简单的技巧,可以将 hdr 数组中每个文字字段的值扩展为对象中的相应值(参见 Generic Object Index )。通过将其括在括号中,您可以在数组中获得选定的字段值。收集到这个数组和标题数组后,应用@tsv 函数来获取表格形式。

jq play snippet - Demo

【讨论】:

  • 很好,很有效。我现在看到我需要自学如何在 JQ 中使用变量。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 2021-01-26
  • 2020-05-14
  • 2020-12-29
  • 2014-07-08
  • 1970-01-01
相关资源
最近更新 更多