Iterate through dictionaries jq - shell

安稳与你 提交于 2020-12-06 06:32:24

问题


I have a JSON like this

{
  "images" : [
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-Small@2x.png",
      "scale" : "2x"
    }
     ......
     ......
    {
      "size" : "60x60",
      "idiom" : "iphone",
      "filename" : "Icon-60@3x.png",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

I want to iterate through each dictionary in images array. For that I wrote

declare -a images=($(cat Contents.json | jq ".images[]"))
for image in "${images[@]}"
do
    echo "image --$image"
done

I am expecting output that each dictionary is printing in an iteration. That is

image --{
  "size" : "29x29",
  "idiom" : "iphone",
  "filename" : "Icon-Small@2x.png",
  "scale" : "2x"
}
image --{
  "size" : "29x29",
  "idiom" : "iphone",
  "filename" : "Icon-Small@3x.png",
  "scale" : "3x"
}
image --{
  "size" : "40x40",
  "idiom" : "iphone",
  "filename" : "Icon-Spotlight-40@2x.png",
  "scale" : "2x"
}

Etc

But its iterating through each and every single elements in each dictionary like

image --{
image --"size":
image --"29x29",
image --"idiom":
image --"iphone",
image --"filename":
....
....
....

What is wrong with my code


回答1:


The problem with your code is that an array initialization in bash looks like this:

declare -a arr=(item1 item2 item3)

Items are separated by space or newline. You can also use:

declare -a arr(
    item1
    item2
    item3
)

However, the jq output in the example contains both spaces and newlines, that's why the reported behaviour is as expected.


Workaround:

I would get the keys first, pipe them to a read loop and then call jq for each item of the list:

jq -r '.images|keys[]' Contents.json | while read key ; do
    echo "image --$(jq ".images[$key]" Contents.json)"
done

You can also use this jq command if you don't care about pretty printing:

jq -r '.images[]|"image --" + tostring' Contents.json

To access a certain property of the subarray you can use:

jq -r '.images|keys[]' Contents.json | while read key ; do
    echo "image --$(jq ".images[$key].filename" Contents.json)"
done

The above node will print the filename property for each node for example.

However this can be expressed much simpler using jq only:

jq -r '.images[]|"image --" + .filename' Contents.json

Or even simpler:

jq '"image --\(.images[].filename)"' Contents.json


来源:https://stackoverflow.com/questions/34529156/iterate-through-dictionaries-jq-shell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!