如何使用JQ从1个JSON创建2个CSV文件

时间:2018-05-23 22:19:00

标签: json csv jq multifile

我有很多相当大的JSON日志需要导入到多个数据库表中。 我可以轻松地解析它们并创建1个CSV用于导入。 但是,我如何解析JSON并获得2个不同的CSV文件作为输出? 简单(废话)例子:

testJQ.log

{"id":1234,"type":"A","group":"games"}
{"id":5678,"type":"B","group":"cars"}

使用

cat testJQ.log|jq --raw-output '[.id,.type,.group]|@csv'>testJQ.csv

我得到一个文件testJQ.csv

1234,"A","games
5678,"B","cars"

但我想得到这个

types.csv

1234,"A"
5678,"B"

groups.csv

1234,"games"
5678,"cars"

这可以在不必解析JSON两次的情况下完成,第一次创建types.csv,第二次创建groups.csv吗?

cat testJQ.log|jq --raw-output '[.id,.type]|@csv'>types.csv
cat testJQ.log|jq --raw-output '[.id,.group]|@csv'>groups.csv

2 个答案:

答案 0 :(得分:1)

您需要运行两次jq,或者与另一个程序一起运行jq以将调用的输出“拆分”为jq。例如,您可以使用以下格式的管道:jq -c ... | awk ...

管道方法的潜在缺点是如果JSON是最终输出,它将是JSONL;但显然这不适用于此。

有很多方法可以制作这样的管道。例如,假设CSV中没有原始换行符:

< testJQ.log jq -r '
    "types",  ([.id,.type] |@csv),
    "groups", ([.id,.group]|@csv)' |
  awk 'NR % 2 == 1 {out=$1; next} {print >> out".csv"}'

或者:

< testJQ.log jq -r '([.id,.type],[.id,.group])|@csv' |
    awk '{ out = ((NR % 2) == 1) ? "types" : "groups"; print >> out".csv"}'

有关其他示例,请参阅例如

处理原始新行

无论您是否将CSV拆分为多个文件,嵌入式原始换行都存在潜在问题。一种方法是将JSON字符串中的“\ n”更改为“\\ n”,例如

jq -r '([.id,.type],[.id,.group])
       | map(if type == "string" then gsub("\n";"\\n") else . end)
       | @csv'

答案 1 :(得分:1)

我认为你可以解决这个问题的一种方法是将一个文件的内容输出到stdout,将其他文件的内容输出到stderr并重定向到单独的文件。当然,你只限于两个文件。

$ <testJQ.log jq -r '([.id,.type]|@csv),([.id,.group]|@csv|stderr|empty)' \
    1>types.csv 2>groups.csv

stderr输出到stderr,但值传播到输出,因此您需要使用empty跟随它以吞下它。

我个人不建议这样做,如果你需要输出到多个文件,我会写一个python脚本(或其他语言)来解析它。