Home > Blockchain >  Index string array by prefix in JQ
Index string array by prefix in JQ

Time:05-29

I'm trying to figure out how to print name of keys and specific sub-sub values from it. My JSON is:

{
  "results": 3,
  "rows": [
    {
      "hostname1": {
        "tags": [
          "owner:TEAM_A",
          "friendlyname:myhost1",
          "x:abc",
          "y:jkl"
        ]
      }
    },
    {
      "hostname2": {
        "tags": [
          "friendlyname:myhost2",
          "owner:TEAM_A",
          "x:def",
          "q:jkl"
        ]
      }
    },
    {
      "hostname3": {
        "tags": [
          "owner:TEAM_A",
          "x:ghi",
          "friendlyname:myhost3",
          "q:jkl"
        ]
      }
    }
  ]
}

What I've already achieved is to print just keys of hostnames:

jq -r '.rows[] | keys[]' example.json
hostname1
hostname2
hostname3

I know how to print key:values from tags array:

jq -r .rows[0].hostname1.tags[0,1] example.json
owner:TEAM_A
friendlyname:myhost1

But I can't figure out how to print

hostname1
          "owner:TEAM_A",
          "friendlyname:myhost1",
hostname2
          "owner:TEAM_A",
          "friendlyname:myhost2",
hostname3
          "owner:TEAM_A",
          "friendlyname:myhost3",

Be aware, that the keys in tags array has different order, so I cannot reach it through .rows[0].hostname1.tags[0,1] I'm looking for something like .rows[0].all_keys.tags[owner,friendlyname]

My bash script was very close, but the order of keys brokes it.

hostnames=`jq -r '.rows[] | keys[]' example.json`
count=0
for i in $hostnames
do
   jq -r .rows[$count].$i\.tags[0,1] example.json
   echo $i
   ((count=count 1))
done

CodePudding user response:

You can use to_entries to convert an object into an array of key-value pairs, then access .key and .value of its items to your own likings. For instance:

jq -r '.rows[] | to_entries[] | [.key, .value.tags[0,1]] | join("\n ")'
hostname1
  owner:TEAM_A
  friendlyname:myhost1
hostname2
  friendlyname:myhost2
  owner:TEAM_A
hostname3
  owner:TEAM_A
  x:ghi

Demo

Another example:

jq -r '
  .rows[] | to_entries[] | [.key, (
    .value.tags[] | select(startswith("owner:", "friendlyname:"))
  )] | join("\n ")
'
hostname1
  owner:TEAM_A
  friendlyname:myhost1
hostname2
  friendlyname:myhost2
  owner:TEAM_A
hostname3
  owner:TEAM_A
  friendlyname:myhost3

Demo

CodePudding user response:

Turning tags into an object first would make it easier to retrieve tags in a particular order.

.rows[][].tags | INDEX(sub(":.*"; "")) | .owner, .friendlyname

Online demo

And it seems like you don't need a shell loop for this task, JQ can do all that and even more on its own.

.rows[]
| keys_unsorted[] as $hostname
| .[$hostname].tags
| INDEX(sub(":.*"; ""))
| $hostname, "\t"   (.owner, .friendlyname)

Online demo

  • Related