EricBDev
EricBDev

Reputation: 1569

Extract values from an array in json in one line in Linux bash. With jq?

Given such a json (very simplified from my real use case), which file is service-def-test.json:

{
    "definition": {
        "services": [{
                "image": {
                    "name": "img1",
                    "tag": "2.0.1"
                }
            }, {
                "image": {
                    "name": "img2",
                    "tag": "1.4.0"
                }
            }, {
                "image": {
                    "name": "img3",
                    "tag": "1.2.5"
                }
            }
        ]
    }
}

I would like to get twice a one-line list of values, so that I could export each line to a variable and proceed it eventually:

images=[img1, img2, img3]
tags=[2.0.1, 1.4.0, 1.2.5]

jq is probably the way to go

jq -r .definition.services[].image.name service-def-test.json

gives

img1
img2
img3

How could I transform that to one line? Could jq directly output what I want? I tried options like -c but I did not manage to have the output in one line. Other though is about used sed or awk to transform the output.

What would be your simplest solution?

Upvotes: 0

Views: 192

Answers (1)

knittl
knittl

Reputation: 265161

Sure. Specify -c/--compact-output and use map to extract an array:

jq -c '.definition.services | map(.image.name)' input.json

Output:

["img1","img2","img3"]

If your requirement is to have the unquoted names (I would be surprised, but who knows), then resort to join/1 and -r/--raw-output:

jq -r '"[\(.definition.services | map(.image.name) | join(","))]"' input.json

Output:

[img1,img2,img3]

All in one go, producing exactly the required output from your question (minus the blanks):

jq -r '
  .definition.services
  | "images=[\(map(.image.name) | join(","))]",
    "tags=[\(map(.image.tag) | join(","))]"
' input.json

But maybe you need those quotes after all? Leverage the fact that arrays will be stringified for you:

jq -r '
  .definition.services
  | "images=\(map(.image.name))",
    "tags=\(map(.image.tag))"
' input.json

Output:

images=["img1","img2","img3"]
tags=["2.0.1","1.4.0","1.2.5"]

Upvotes: 1

Related Questions