使用 jq 解析 JSON 数据并转换为 csv

sam*_*sam 1 shell-script jq

我正在下载 api json 数据并将最终结果转换为 csv 文件。

样本数据格式如下:

{
    "content": [{
            "Title": "abc",
            "brand": "xyz",
            "information": {
                "c1": "101",
                "c2": "11111",
                "c3": "a,b,c,d,e:abc."
            }
        },
        {
            "Title": "RX100",
            "brand": "Yamaha",
            "information": {
                "c1": "102",
                "c2": "22222",
                "c3": "a."
            }
        },
        {
            "Title": "victor",
            "brand": "TVS",
            "information": {
                "c1": "103",
                "c2": "33333",
                "c3": "a,b,c"
            }
        },
        {
            "Title": "R15",
            "brand": "Yamaha",
            "information": {
                "c1": "104",
                "c2": "44444",
                "c3": "a,b"
            }
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我已经根据Title的数量成功下载并转换为多个csv。转换成多个 csv 文件后,数据如下所示。

Headers-> c1,c2,c3
csv1-->   101,11111,a,b,c,d,e:abc.
csv2-->   102,22222,a.
csv3-->   103,33333,a,b,c.
csv4-->   104,44444,a,b.
Run Code Online (Sandbox Code Playgroud)

但我想要以下表格中的上述数据。

Headers-> c1,c2,c3,c4,c5,c6,c7
csv1-->   101,11111,a,b,c,d,e:abc.
csv2-->   102,22222,a.
csv3-->   103,33333,a,b,c.
csv4-->   104,44444,a,b.
Run Code Online (Sandbox Code Playgroud)

是否可以使用 json.json 以我的 json 文件中存在的“,”为基础将 c3 划分为不同数量的列。列 c3 将根据存在的元素数量进行划分,并且将是 c3 数据的最大值。

Mic*_*mer 5

对于这个确切的数据,

jq -r '.content[].information | [.c1, .c2, .c3] | join(",")' < sample.json
Run Code Online (Sandbox Code Playgroud)

会起作用 - 只需在三列之间插入逗号即可复制合并的 CSV 文件的效果。对于更复杂的真实数据,尤其是数字,这将更有效:

jq -r '.content[].information | [.c1, .c2, (.c3|split(",")|.[])] | @csv' < sample.json
Run Code Online (Sandbox Code Playgroud)

这一个都相当标准.c3|split(",")|.[]

  1. 提取第 3 列的值
  2. 将该值拆分为逗号数组
  3. 将该数组展平

@csv然后将数组转换为 CSV 格式。这将为您的示例文件生成以下输出:

"101","11111","a","b","c","d","e:abc."
"102","22222","a."
"103","33333","a","b","c"
"104","44444","a","b"
Run Code Online (Sandbox Code Playgroud)

如果您不想要引号,最可靠的方法是使用@tsv并替换选项卡:

jq -r '.content[].information|[.c1, .c2, .c3|split(",")|.[]] | @tsv|gsub("\t"; ",")' < sample.json
Run Code Online (Sandbox Code Playgroud)

如果您的所有值都是字符串,您也可以join(",")再次使用。


如果您还想c1,...c7创建文字标题行,可以这样做:

jq -r '[.content[].information|[.c1, .c2, (.c3|split(",")|.[])]] | (([range([.[] | length] | max)|"c" + (.+1|tostring)]|join(",")), (.[] | join(",")))' < sample.json
Run Code Online (Sandbox Code Playgroud)

有三部分:第一部分像以前一样创建列数组,然后其他两部分将其用作输入:

  1. ([range([.[] | length] | max)|"c" + (.+1|tostring)]|join(",")) 生成标题行:它通过生成行长度数组来找到任何行的最大长度,创建一个范围 0..maximum 并映射到它以创建一个“c1”..“c7”数组,然后将它们全部连接起来连同逗号。
  2. (.[] | join(","))类似于我们之前的下半场,同样的事情也@csv适用。