Home > front end >  Extract values from an array in json in one line in Linux bash. With jq?
Extract values from an array in json in one line in Linux bash. With jq?

Time:01-24

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?

CodePudding user response:

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"]
  • Related