使用 jq 将 JSON 对象添加到数组

使用 jq 将 JSON 对象添加到数组

我的目标是使用bash 中命令jq的输出来输出 JSON 对象。find它可以是单行命令,也可以是 bash 脚本。

我有这个命令,它从每行输出创建 JSON 对象:

find ~/ -maxdepth 1 -name "D*" | \
while read line; \
do jq -n \
--arg name "$(basename "$line")" \
--arg path "$line" \
'{name: $name, path: $path}'; \
done

输出如下所示:

{
  "name": "Desktop",
  "path": "/Users/username/Desktop"
}
{
  "name": "Documents",
  "path": "/Users/username/Documents"
}
{
  "name": "Downloads",
  "path": "/Users/username/Downloads"
}

但我需要这些对象位于一个数组中,并且我需要该数组是父对象的单个键的值items,如下所示:

{"items": [
    {
      "name": "Desktop",
      "path": "/Users/username/Desktop"
    },
    {
      "name": "Documents",
      "path": "/Users/username/Documents"
    },
    {
      "name": "Downloads",
      "path": "/Users/username/Downloads"
    }
  ]
}

我尝试将方括号添加到jq每行 ( '[{name: $name, path: $path}]';) 的输出字符串中,并且添加方括号,但不添加数组元素之间的逗号。

我找到了可能的解决方案这里但我不知道如何在循环每一行时使用它们。

答案1

这个jq 1.5 inputs流媒体过滤器的技巧似乎可以做到

... | jq -n '.items |= [inputs]'

前任。

$ find ~/ -maxdepth 1 -name "D*" | 
    while read line; do 
      jq -n --arg name "$(basename "$line")" \
            --arg path "$line" \
        '{name: $name, path: $path}'
    done | jq -n '.items |= [inputs]'
{
  "items": [
    {
      "name": "Downloads",
      "path": "/home/steeldriver/Downloads"
    },
    {
      "name": "Desktop",
      "path": "/home/steeldriver/Desktop"
    },
    {
      "name": "Documents",
      "path": "/home/steeldriver/Documents"
    }
  ]
}

答案2

jq直接从调用find,然后用 收集结果数据来jq构建最终输出,无需任何 shell 循环:

find ~ -maxdepth 1 -name '[[:upper:]]*' \
    -exec jq -n --arg path {} '{ name: ($path|sub(".*/"; "")), path: $path }' \; |
jq -n -s '{ items: inputs }'

通过为每个找到的路径名创建一个 JSON 对象来jq执行。-exec它会删除路径名中直到值的最后一个斜杠的所有内容name,并按原样使用路径名作为值path

最后使用jq读取数据到find数组中-s,然后将其作为items数组插入到新的 JSON 对象中。最后的jq调用也可以这样写jq -n '{ items: [inputs] }

示例结果(请注意,我使用[[:upper:]*代替的模式D*):-namefind

{
  "items": [
    {
      "name": "Documents",
      "path": "/home/myself/Documents"
    },
    {
      "name": "Mail",
      "path": "/home/myself/Mail"
    },
    {
      "name": "Work",
      "path": "/home/myself/Work"
    }
  ]
}

答案3

如果您不介意使用编程语言,这非常简单。这是一个 PHP 示例:

<?php
$m1 = [
   'items' => []
];
$a1 = glob('~/D*');
foreach ($a1 as $s1) {
   $m1['items'][] = [
      'name' => basename($s1),
      'path' => $s1
   ];
}
echo json_encode($m1, JSON_PRETTY_PRINT);

相关内容