使用 jq 和 bash 为数组中的每个对象运行命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43192556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using jq with bash to run command for each object in array
提问by danielrvt
How can I run a bash command for every json object in a json array using jq? So far I have this:
如何使用 jq 为 json 数组中的每个 json 对象运行 bash 命令?到目前为止,我有这个:
cat credentials.json | jq -r '.[] | .user, .date, .email' | mycommand -u {user} -d {date} -e {email}
This doesn't seem to work. How can I take the parameters out of the json array into my command?
这似乎不起作用。如何将参数从 json 数组中取出到我的命令中?
My json file looks something like this:
我的 json 文件看起来像这样:
[
"user": "danielrvt",
"date": "11/10/1988",
"email": "[email protected]",
...
]
回答by chepner
Your best bet is probably to output each record in something like TSV format, then read that from a shell loop.
您最好的选择可能是以类似 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
itself doesn't have anything like a system
call to run an external command from within a filter, although it seems that they are working on it.
jq
本身没有任何类似system
调用从过滤器内运行外部命令的功能,尽管它们似乎正在处理它。
回答by kojiro
You could have jq
output the commands to execute, something like
您可以jq
输出要执行的命令,例如
.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"
Then execute it. Something like
然后执行它。就像是
bash <(jq -r '.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"' foo)
回答by Marcin
With xargs:
使用 xargs:
curl localhost:8082/connectors | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}'
Or equivalently, to show the output of that first curl:
或者等效地,显示第一个 curl 的输出:
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 .[]
strips off one level of containment, so that a list becomes output as one line per item.
jq .[]
剥离一层包含,以便列表成为每个项目一行的输出。
xargs -L1
processes one line at a time
xargs -L1
一次处理一行
xargs -I'{}'
specifies that the string {}
be replaced with the input line when invoking the following command.
xargs -I'{}'
指定{}
在调用以下命令时将字符串替换为输入行。
xargs
is essentially a map operator for the shell.
xargs
本质上是外壳的映射运算符。
回答by Haochen Xie
I came across the same problem recently where xargs doesn't help that much due to the relatively complicated set of arguments I wanted to pass around. Thus I implemented an sh
filter (and its friends) to jq. I haven't yet had enough time to write documentation and tests for it so not creating a PR for it to become a part of the official codebase yet. So now it's only for the ones who are willing to compile this version themselves:
我最近遇到了同样的问题,由于我想传递的一组相对复杂的参数,xargs 没有太大帮助。因此,我sh
为 jq实现了一个过滤器(及其朋友)。我还没有足够的时间为其编写文档和测试,因此还没有为其创建 PR 使其成为官方代码库的一部分。所以现在只给那些愿意自己编译这个版本的人:
回答by Chris Gibb
Here is another variation which I based on the answer from @chepner.
这是我基于@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
I used jq's -c option to output "compact" jsons, so they are all on one line.
我使用 jq 的 -c 选项输出“紧凑”json,所以它们都在一行上。
In combination with IFS=$"\n"
, I was able to loop over each item in the input json's array and do what I wanted to do.
与 结合使用IFS=$"\n"
,我能够遍历输入 json 数组中的每个项目并做我想做的事情。
So, with an input of
所以,输入
[
{
"host": "host1",
"settings": {}
},
{
"host": "host1",
"settings": {}
}
]
the output is
输出是
start
host1
end
start
host2
end