json - 使用 jq,将 csv 文件转换为 json,使用 csv 文件名作为顶级对象名称

标签 json bash csv jq

我需要使用 bash 和 jq v1.6 将一堆 csv 文件转换为 json。 (由于对允许在服务器上运行的脚本类型的限制,我不能使用其他脚本语言)。 JSON 或 jq 都不是我技能的重要组成部分。

我需要使用 csv 文件名作为 json 对象名称,读取 csv 以从 header 中获取字段名,并进行一些重新映射以将“所有者”移动到列表(数组?)名称。

所以,拿这个:

serverset1.csv

location,category,ip,owner
set1rack1,webserver,127.0.0.1,Customer1
set1rack2,appserver,127.0.0.2,Customer1
set1rack1,webserver,127.0.0.3,Customer2
set1rack2,appserver,127.0.0.4,Customer2

对此

[
   {
      "serverset1":[
         {
            "Customer1":[
               {
                  "location":"set1rack1",
                  "category":"webserver",
                  "address":"127.0.0.1"
               },
               {
                  "location":"set1rack2",
                  "category":"appserver",
                  "address":"127.0.0.2"
               }
            ],
            "Customer2":[
               {
                  "location":"set1rack1",
                  "category":"webserver",
                  "address":"127.0.0.3"
               },
               {
                  "location":"set1rack2",
                  "category":"appserver",
                  "address":"127.0.0.4"
               }
            ]
         }
      ]
   }
]

我做到了这一点:

filename="serverset1.csv"; \
cat "$filename" | jq --slurp --raw-input --raw-output \
'
  split("\n") | .[1:] | map(split(",")) |
    map(
         {
            "location": .[0],
            "category": .[1],
            "address": .[2],
            "owner": .[3]
         }
    )
' 

产生这个:

[
  {
    "location": "set1rack1",
    "category": "webserver",
    "address": "127.0.0.1",
    "owner": "Customer1"
  },
  {
    "location": "set1rack2",
    "category": "appserver",
    "address": "127.0.0.2",
    "owner": "Customer1"
  },
  {
    "location": "set1rack1",
    "category": "webserver",
    "address": "127.0.0.3",
    "owner": "Customer2"
  },
  {
    "location": "set1rack2",
    "category": "appserver",
    "address": "127.0.0.4",
    "owner": "Customer2"
  }
]

但后来我遇到了语法墙。

感谢任何帮助。

~杰米

最佳答案

使用input_filename 获取输入文件名。要跳过第一行,请使用不带 -n 选项的 inputs:

jq -R '
  inputs
  | [splits(", *")] as $row
  | {(input_filename): { ($row[3]): $row[:3] }}
' serverset1.csv

这会生成一个“文件名”对象流,然后您可以通过修改脚本(而不是再次调用 jq)轻松地将其组装成一个数组。

如果输入文件没有头文件,则使用-n 命令行选项。

注意事项

  1. jq 可以读取非常简单的 CSV 文件,但不太适合读取一般的 CSV 文件。如果 jq 无法轻松正确读取您的 CSV 文件,您可以使用众多出色的替代方法之一将 CSV 文件转换为 TSV 文件。

  2. 上述程序不会尝试将数字或 bool 字符串转换为 JSON 数字或 bool 值;然而,通过对上述程序进行适当的调整,可以使用 jq 轻松完成任何此类转换。

关于json - 使用 jq,将 csv 文件转换为 json,使用 csv 文件名作为顶级对象名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66130421/

相关文章:

php - jquery + php + json 有点迷失

java - 如何将输入流文件分配给json?

python - 使用 python 使用 JSON 自动更新 MYSQL 表

bash - 如何使用bash获取带有fo o.bar名称的文件夹的大小?

csv - 密码保护 CSV 文件

python - 将格式错误的 csv 文件转换为 numpy 数组

json - Sequelize : How to return relationships as JSON attribute?

linux - 在 bash 脚本中,$'\0' 的计算结果是什么?为什么?

linux - 遍历列表并创建目录(或者为什么这个循环中断)

mysql - 如何将 csv-import 西里尔文本导入 PhpMyAdmin 中的 latin1-swedish-ci 编码表中?