使用 jq 和 bash 为数组中的每个对象运行命令

问题描述 投票:0回答:5

如何使用

jq
为 JSON 数组中的每个 JSON 对象运行 Bash 命令?到目前为止我有这个:

cat credentials.json | jq -r '.[] | .user, .date, .email' | mycommand -u {user} -d {date} -e {email}

这似乎不起作用。如何将 JSON 数组中的参数取出到我的命令中?

我的 JSON 文件看起来像这样:

[
   "user": "danielrvt",
   "date": "11/10/1988",
   "email": "[email protected]",
   ...
]
bash jq
5个回答
75
投票

您最好的选择可能是以 TSV 格式输出每条记录,然后从 shell 循环中读取该记录。

jq -r '.[]|[.user, .date, .email] | @tsv' |
  while IFS=$'\t' read -r user date email; do
    mycommand -u "$user" -d "$date" -e "$email"
  done

jq
本身没有像
system
调用那样从过滤器内运行外部命令的功能,尽管看起来他们正在处理它


49
投票

使用 xargs:

curl localhost:8082/connectors | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}' 

或者等效地,显示第一个卷曲的输出:

echo '["quickstart-file-sink4","quickstart-file-source","quickstart-file-sink","quickstart-file-sink2","quickstart-file-sink3","quickstart-file-source2"]' | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}' 

jq .[]
剥离一级包含,以便列表成为每项一行输出。

xargs -L1
一次处理一行

xargs -I'{}'
指定在调用以下命令时将字符串
{}
替换为输入行。

xargs
本质上是 shell 的映射运算符。


33
投票

您可以

jq
输出要执行的命令,例如

.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"

然后执行它。类似的东西

bash <(jq -r '.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"' foo)

22
投票

这是我基于@chepner 的答案的另一种变体。

echo "$config" | jq -c '.[]' |
while IFS=$"\n" read -r c; do
    echo "start"
    host=$(echo "$c" | jq -r '.host')
    echo $host
    echo "end"
done

我使用jq的-c选项来输出“紧凑”的json,因此它们都在一行上。

IFS=$"\n"
结合,我能够循环输入 json 数组中的每个项目并执行我想做的操作。

因此,输入

[
 {
  "host": "host1",
  "settings": {}
 },
 {
  "host": "host2",
  "settings": {}
 }
]

输出是

start
host1
end
start
host2
end

6
投票

我最近遇到了同样的问题,由于我想传递相对复杂的参数集, xargs 并没有多大帮助。因此,我为 jq 实现了一个

sh
过滤器(及其朋友)。我还没有足够的时间为它编写文档和测试,因此还没有创建 PR 以使其成为官方代码库的一部分。所以现在只适合那些愿意自己编译这个版本的人:

https://github.com/haochenx/jq/tree/sh-support

© www.soinside.com 2019 - 2024. All rights reserved.