📜  json 到 csv - Shell-Bash (1)

📅  最后修改于: 2023-12-03 15:02:26.011000             🧑  作者: Mango

Json 到 Csv - Shell-Bash

在日常的开发工作中,我们时常需要将数据进行转换成不同格式,其中 Json 和 Csv 的转换是比较常见的一种。此篇介绍如何利用 Shell-Bash 来进行 Json 到 Csv 的转换。

前置知识
  • Shell-Bash 基础语法(变量、循环、判断、函数、管道等)
  • Json 基础语法
  • Csv 基础语法
实现方法
读取 Json 数据

在 Shell-Bash 中,可以利用 jq 工具来解析 Json 数据。安装方式如下:

# Debian / Ubuntu
$ sudo apt-get install jq

# RedHat / CentOS
$ sudo yum install jq

# macOS
$ brew install jq

例如我们有一个 Json 文件 data.json,内容如下:

{
  "students": [
    {
      "name": "Tom",
      "age": 18,
      "gender": "male",
      "scores": [88, 90, 92]
    },
    {
      "name": "Jerry",
      "age": 19,
      "gender": "female",
      "scores": [90, 92, 94]
    }
  ]
}

可以使用以下命令读取其中的数据:

# 读取所有数据
$ cat data.json | jq '.'

# 读取某个字段的数据
$ cat data.json | jq '.students[0].name'

# 读取数组的数据
$ cat data.json | jq '.students[0].scores[]'
转换为 Csv 格式

通过 jq 解析后,得到的是 Json 格式的数据,需要进一步转换成 Csv 格式。以下是一个比较通用的转换方法:

# 定义变量
delimiter=","   # Csv 文件的分隔符
array_start=0   # 数组起始下标
array_end=-1    # 数组结束下标,默认-1表示全部
keys=()         # 列名集合,动态生成

# 解析Json数据
cat data.json | jq -r '.students[] | @csv'

# 读取列名
cat data.json | jq -r '.students[0] | keys[]' | while read key
do
  if [ "$key" = "scores" ]
  then
    count=($(cat data.json | jq ".students[$array_start:$array_end] | .$key[] | length" | sort -u))
    for (( i=0; i<$count; i++ ))
    do
      keys+=("\"$key[$i]\"")
    done
  else
    keys+=("\"$key\"")
  fi
done

# 生成 Csv 数据
cat data.json | jq -r --arg delimiter "$delimiter" --argjson keys "${keys[*]}" \
  -r '.students[0] | to_entries | sort_by(.key) | .[].value | @csv' | tr -d '\r' |
  sed "1s/.*/${keys[@]}/" | sed "2,$ s|$|${delimiter//\\/}|g"

以上脚本中,通过 jq 工具解析出列名集合,在第一行输出,然后输出数据行,通过 sed 工具将换行符替换成 Csv 文件的分隔符。

以上方法仅限于 Json 中不包含嵌套的数组。如果有嵌套的数组,可以参考flatten函数的实现方法。附上代码供参考:

flatten() {
    if [[ $(echo "$1" | jq -r 'type') == 'array' ]]; then
        jq -r '
            map(
                if type == "object" then
                    to_entries | flatten
                elif type == "array" then
                    flatten
                else
                    .
                end
            ) | add
        '
    else
        echo "$1"
    fi
}

# 使用方式如下:
flatten "$1" | jq -r 'map(tostring | gsub("\""; "\"\"")) | @csv'
总结

以上介绍了如何通过 Shell-Bash 实现 Json 到 Csv 的转换。其中需要注意的点是:

  • 利用 jq 工具解析 Json 数据
  • 动态生成列名集合
  • 将 Json 数据转换成 Csv 格式

在实际应用中,需要根据实际的数据结构进行适当的调整。此篇介绍的方法仅供参考。