0

I am extending here my recent question about jq since my requirements changed and I am still confused with map function.

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

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

I now would like to get a one-line list of values:

[img1:2.0.1, img2:1.4.0, img3:1.2.
to store eventually in a COMPONENT_IMAGES variable.

From the previous answer,

jq -r '.definition.services | " "COMPONENT_IMAGES=\"\(map(.image.name, .image.tag) | join(", "))\"" ' service-def-test.json

generates

COMPONENT_IMAGES="img1, 2.0.1, img2, 1.4.0, img3, 1.2.5"

but this I want only 3 items in my output array.

I am looking to get

COMPONENT_IMAGES="img1:2.0.1, img2:1.4.0, img3:1.2.5"

What am I missing here? Thanks!

1
  • I don't use jq, but ... would replacing ... map(.image.name, .image.tag) ... with ... map(.image.name:.image.tag) ... be accepted by syntax and give you what you want? Commented Jan 26, 2023 at 20:26

1 Answer 1

3

map lets you filter each array item individually. Here, we descend to .image, and concatenate the value of .name, a literal colon ":", and the value of .tag. The mapped array can then be joined with a glue string ", ".

jq -r '
  .definition.services
  | "COMPONENT_IMAGES=\"" + (map(.image | .name + ":" + .tag) | join(", ")) + "\""
'
COMPONENT_IMAGES="img1:2.0.1, img2:1.4.0, img3:1.2.5"

Demo


If you prefer using string interpolation, here's its equivalent:

jq -r '
  .definition.services
  | "COMPONENT_IMAGES=\"\(map(.image | "\(.name):\(.tag)") | join(", "))\""
' 
COMPONENT_IMAGES="img1:2.0.1, img2:1.4.0, img3:1.2.5"

Demo

Sign up to request clarification or add additional context in comments.

4 Comments

Suggestion, you could get rid of adding the literal quotes by just converting the string to json. Functionally the same. "COMPONENT_IMAGES=\(map(...)|...|tojson)"
@JeffMercado Good idea! @sh would be another option in view of the purpose of the construction ("to store eventually in a COMPONENT_IMAGES variable").
eventually, I need only a space (without ',') as separator, and don't need the "" around so I am using this: "COMPONENTS="+ (map(.image | .name + ":" + .tag) | join(" "))'
fyi, the whole is set in a Gitlab job, and the output from jq is set in a env file ( > extract.env ) and then as artifacts: reports: dotenv: extract.env

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.