如何使用jq或任何工具合并目录中的多个json文件?

时间:2020-07-23 04:38:36

标签: json jq

我正在尝试将目录中的所有json文件合并(可能很多)。

我知道,如果只有2个文件,我可以使用jq -s . file1.json file2.json。但是,当我尝试使用jq -s . file*.json之类的通配符时,它将失败。有想法吗?

2 个答案:

答案 0 :(得分:0)

在等待jq的解决方案时,让我解决问题“ ...或任何工具?”

不同的人通过“合并”来表示不同的事物,因此这里假设进行简单的递归JSON合并,然后使用jtc(另一个工具),解决方案将是这样(对于任意数量的文件):

  • 将所有JSON读入一个超级JSON数组
  • 将其余读取的JSON合并到第一个孩子(第一个读取的JSON)
  • 在数组中输出结果第一个JSON子级
jtc -J / -w[0] -mi[1:] / -w[0] *.json 

为了说明该解决方案,以下是它如何与几个任意JSON文件一起工作的方法:

bash $ jtc -tc file1.json 
{
   "days": {
      "2020-05-18": { "seconds": 60 },
      "2020-05-19": { "seconds": 30 },
      "2020-05-20": { "seconds": 1400 }
   },
   "total": { "seconds": 1490 }
}
bash $ jtc -tc file2.json 
{
   "days": {
      "2020-05-20": { "seconds": 95 },
      "2020-05-21": { "seconds": 80 },
      "2020-05-22": { "seconds": 120 }
   },
   "total": { "seconds": 295 }
}
bash $ jtc -J / -w[0] -mi[1:] / -w[0] -tc file*.json
{
   "days": {
      "2020-05-18": { "seconds": 60 },
      "2020-05-19": { "seconds": 30 },
      "2020-05-20": {
         "seconds": [ 1400, 95 ]
      },
      "2020-05-21": { "seconds": 80 },
      "2020-05-22": { "seconds": 120 }
   },
   "total": {
      "seconds": [ 1490, 295 ]
   }
}
bash $ 

-tc标志仅用于在此处以紧凑格式显示JSON

PS。碰巧我是jtc工具的创建者-Unix JSON处理实用程序。

答案 1 :(得分:0)

答案 这是 jq 的答案...有关更多信息,请参阅下面的说明:

s="*.json"; jq -s "`x=-1; n=$(ls $s | wc -l); while [ $((x++)) -lt $(($n-2)) ]; do printf ".[$x] * " ; done; printf ".[$(($n-1))]";`" $s

分步说明

要使用 jq 合并两个 json 文件,请使用以下命令:

jq -s ".[0] * .[1]" file1.json file2.json

现在合并三个json文件:

jq -s ".[0] * .[1] * .[2]" file1.json file2.json file3.json

让我们遵循相同的逻辑并使用通配符对 n 个文件进行概括。困难的部分是生成字符串 .[0] * .[1] ... .[n-1]

首先让我们找到 n。 n 是文件夹中 json 文件的数量。所以:

ls *.json | wc -l

现在让我们编写一个循环来构建字符串“.[1] * .. * .[a] * .[a+1] * .. * .[n-2] *”。这个字符串的内核是 .[a] * 所以:

x=-1; n=$(ls *.json | wc -l); while [ $((x++)) -lt $(($n-2)) ]; do printf ".[$x] * " ; done;

好的,现在让我们添加最后一部分 .[n-1]

x=-1; n=$(ls *.json | wc -l); while [ $((x++)) -lt $(($n-2)) ]; do printf ".[$x] * " ; done; printf ".[$(($n-1))]";

现在让我们将该字符串传递给 jq 命令...然后让我们参数化 *.json 以便我们可以轻松地将其替换为我们想要的任何内容:

s="*.json"; jq -s "`x=-1; n=$(ls $s | wc -l); while [ $((x++)) -lt $(($n-2)) ]; do printf ".[$x] * " ; done; printf ".[$(($n-1))]";`" $s

瞧!