使用 jq 循环 json 以获取多个值
Loop through json using jq to get multiple value
这里是 volumes.json :
{
"Volumes": [
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "vol-rescue-system",
"Key": "Name"
}
],
"VolumeId": "vol-00112233",
},
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "vol-rescue-swap",
"Key": "Name"
}
],
"VolumeId": "vol-00112234",
},
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "vol-rescue-storage",
"Key": "Name"
}
],
"VolumeId": "vol-00112235",
}
]
}
我需要同时获取 VolumeId
和 Tags.Value
的值以用作调用另一个命令的输入。从 json 数组中获取单个值很容易,但我无法从中提取 多个值 并将其传递给另一个 bash 命令。
我可以使用这个获得单个值:
cat volumes.json |jq -r '.Volumes[].VolumeId' |while read v; do another_bash_command $v; done
但我无法获得多个值,因为这是错误的:
cat volumes.json |jq -r '.Volumes[].VolumeId, .Volumes[].Tags[].Value' |while read v w; do another_bash_command $v $w; done
因为它将循环 6 次结果而不是 3 次。
And,如何将循环中的多个 json 值传递给 bash 数组,以便我可以更好地使用该值?比如VolumeId-> $arr[0][0]
, Tags.Value-> $arr[0][1]
, AvailabilityZone-> $arr[0][2]
...等等。我搜索了 SO 和 jq 文档,并尝试了 readarray
,但仍然找不到解决方案:( 感谢您提供的任何帮助。
在我看来,您想在同一行上输出两个值(VolumeId
和 Tags[].Value
)?
如果是这样,那么一个简单的字符串连接就足够了:
$ jq -r '.Volumes[] | .VolumeId + " " + .Tags[].Value' volumes.json
vol-00112233 vol-rescue-system
vol-00112234 vol-rescue-swap
vol-00112235 vol-rescue-storage
然后可以在管道中使用上面的 while-read
:
$ cat my_script
jq -r '.Volumes[] | .VolumeId + " " + .Tags[].Value' volumes.json \
| while IFS= read -r volumeId tagValue; do
other_command "$volumeId" "$tagValue"
done
您应该注意,如果 Tags
中有多个元素,结果将反映这一点。然而,这可以通过引用 Tags
中的第一个元素来避免:.Tags[0].Value
正如@andlrc 观察到的那样,如果任何 Tags 数组的元素多于或少于一个,您可能需要决定您真正想要的是什么。假设您在所有情况下都需要 Tags[0]
,我建议您考虑使用 @tsv,如下所示:
jq -r '.Volumes[] | [.VolumeId, .Tags[0].Value] | @tsv' volumes.json
如果任何 .VolumeId
或 .Tags[0].Value
值包含空格、制表符、换行符等,这将特别合适。关键是 @tsv 将以标准方式处理这些,所以处理这对值也可以以标准方式完成。例如。使用 awk,您可以与 awk -F\t
成对阅读;使用 bash、IFS=$'\t'
等
我知道问题是关于如何使用 jq
获取信息,但也可以使用 --query
标志直接从 aws cli 直接获取预期参数。
aws ec2 describe-volumes --query "Volumes[].[VolumeId, Tags[].Value]" --output text
这里是 volumes.json :
{
"Volumes": [
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "vol-rescue-system",
"Key": "Name"
}
],
"VolumeId": "vol-00112233",
},
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "vol-rescue-swap",
"Key": "Name"
}
],
"VolumeId": "vol-00112234",
},
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "vol-rescue-storage",
"Key": "Name"
}
],
"VolumeId": "vol-00112235",
}
]
}
我需要同时获取 VolumeId
和 Tags.Value
的值以用作调用另一个命令的输入。从 json 数组中获取单个值很容易,但我无法从中提取 多个值 并将其传递给另一个 bash 命令。
我可以使用这个获得单个值:
cat volumes.json |jq -r '.Volumes[].VolumeId' |while read v; do another_bash_command $v; done
但我无法获得多个值,因为这是错误的:
cat volumes.json |jq -r '.Volumes[].VolumeId, .Volumes[].Tags[].Value' |while read v w; do another_bash_command $v $w; done
因为它将循环 6 次结果而不是 3 次。
And,如何将循环中的多个 json 值传递给 bash 数组,以便我可以更好地使用该值?比如VolumeId-> $arr[0][0]
, Tags.Value-> $arr[0][1]
, AvailabilityZone-> $arr[0][2]
...等等。我搜索了 SO 和 jq 文档,并尝试了 readarray
,但仍然找不到解决方案:( 感谢您提供的任何帮助。
在我看来,您想在同一行上输出两个值(VolumeId
和 Tags[].Value
)?
如果是这样,那么一个简单的字符串连接就足够了:
$ jq -r '.Volumes[] | .VolumeId + " " + .Tags[].Value' volumes.json
vol-00112233 vol-rescue-system
vol-00112234 vol-rescue-swap
vol-00112235 vol-rescue-storage
然后可以在管道中使用上面的 while-read
:
$ cat my_script
jq -r '.Volumes[] | .VolumeId + " " + .Tags[].Value' volumes.json \
| while IFS= read -r volumeId tagValue; do
other_command "$volumeId" "$tagValue"
done
您应该注意,如果 Tags
中有多个元素,结果将反映这一点。然而,这可以通过引用 Tags
中的第一个元素来避免:.Tags[0].Value
正如@andlrc 观察到的那样,如果任何 Tags 数组的元素多于或少于一个,您可能需要决定您真正想要的是什么。假设您在所有情况下都需要 Tags[0]
,我建议您考虑使用 @tsv,如下所示:
jq -r '.Volumes[] | [.VolumeId, .Tags[0].Value] | @tsv' volumes.json
如果任何 .VolumeId
或 .Tags[0].Value
值包含空格、制表符、换行符等,这将特别合适。关键是 @tsv 将以标准方式处理这些,所以处理这对值也可以以标准方式完成。例如。使用 awk,您可以与 awk -F\t
成对阅读;使用 bash、IFS=$'\t'
等
我知道问题是关于如何使用 jq
获取信息,但也可以使用 --query
标志直接从 aws cli 直接获取预期参数。
aws ec2 describe-volumes --query "Volumes[].[VolumeId, Tags[].Value]" --output text