使用jq循环遍历JSON以获取多个值

12

这里是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",
    }
]
}

我需要同时获取VolumeIdTags.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

因此,循环的次数将从3次增加到6次。

并且,我如何将这些多个json值传递给bash数组,以便我可以更好地使用值?像VolumeId-> $arr [0] [0]Tags.Value-> $arr [0] [1]AvailabilityZone-> $arr [0] [2]等。我已经在SO和jq文档中搜索过,并尝试过readarray,但仍然无法找到解决方案:(感谢任何给予的帮助。

3个回答

24

我觉得你想要在同一行输出两个值 (VolumeIdTags[].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一起在管道中使用:
jq -r '.Volumes[] | .VolumeId + " " + .Tags[].Value' volumes.json \
| while read -r volumeId tagValue; do
  other_command "$volumeId" "$tagValue"
done

请注意,如果Tags中有多个元素,则结果将反映出来。但是,可以通过引用Tags中的第一个元素来避免这种情况:.Tags [0] .Value

IFS=部分似乎不正确。您应该将其删除或使用IFS=" "来显式设置IFS为空格字符" "。如果保留该部分,则volumeId也将包含tagValue,而tagValue将为空。 - lanoxx
@lanoxx 是的,我认为你是正确的。 - Andreas Louv

9

正如@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'等。


3

我知道这个问题是关于如何使用jq获取信息的,但也可以直接使用aws cli中的--query标志直接获取所需的参数。

aws ec2 describe-volumes --query "Volumes[].[VolumeId, Tags[].Value]" --output text

1
jamespath(用于--query)非常棒,可惜有些事情你无法使用它来完成,而这些事情你可以使用jq来实现(例如参见https://news.ycombinator.com/item?id=16400320,justin_oaks在2018年2月17日的评论)。 - Oliver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接