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

时间:2017-04-03 19:13:56

标签: bash jq

如何使用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": "myemail@domain.com",
   ...
]

5 个答案:

答案 0 :(得分:16)

您最好的选择可能是以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调用来从过滤器中运行外部命令,尽管看起来they are working on it

答案 1 :(得分:8)

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

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

然后执行它。像

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

答案 2 :(得分:4)

使用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的map运算符。

答案 3 :(得分:2)

最近我遇到了一个相同的问题,由于我想要传递的参数相对复杂,xargs并没有太大帮助。因此,我为jq实现了一个sh过滤器(及其朋友)。我还没有足够的时间为其编写文档和测试,因此尚未创建PR使其成为正式代码库的一部分。因此,现在仅适用于愿意自己编译此版本的人:

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

答案 4 :(得分:2)

这是我根据@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": "host1",
  "settings": {}
 }
]

输出为

start
host1
end
start
host2
end