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

使用jq和bash为数组中的每个对象运行命令,bash,jq,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"

如何使用
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",
   ...
]

最好的办法可能是以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
本身没有类似于
系统
的调用来从过滤器中运行外部命令,尽管看起来是这样的。

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

.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"
bash <(jq -r '.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"' foo)
然后执行它。差不多

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

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的映射操作符

我最近遇到了同样的问题,因为我想传递一组相对复杂的参数,所以xargs没有太大帮助。因此,我对jq实现了一个
sh
过滤器(及其朋友)。我还没有足够的时间为它编写文档和测试,所以还没有为它创建一个PR,使其成为官方代码库的一部分。所以现在只有那些愿意自己编译这个版本的人:


这里是另一个变体,我是根据@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

我看了你的密码。我喜欢这个主意。您添加到
src/builtin.c
中的一些代码是重复的,需要简化,但我认为您应该对stedolan/jq打开一个pull请求。这是一个很好的选项,用于迭代一个值数组并对每个值执行一个命令。它不需要多行脚本,也不需要生成命令的步骤和执行命令的步骤
xargs
是一个很棒的命令。我一个字母一个字母地复制了它,但它不起作用:curl:(3)URL位置28的大括号内的空字符串:localhost:8082/connectors/{}当执行简单的“xargs echo”输出时,jq将打印出来,但永远不会使用替换标记(.propname)是我所需要的。|@sh管道是每个单独的属性吗?这与(.user)有什么不同?@sh保证每个参数都被正确引用,这样shell就不会进行字拆分或扩展globs(如果这是得到输出的话)。假设有人设法删除一个文件,如
{“email”:“daniel;rm-rf*,…}