Using jq, how do I substitute a variable within a string?
Asked Answered
F

1

1

When given a string in JSON where I'd like only a part of it templated/substituted:

{
  "title": "Where the $color Fern Grows"
}

Trying to template that with jq args doesn't seem to work:

cat example.json | jq --arg color "Red"

jq doesn't like the substitution and returns the un-templated example.json with $color in the output

How can you tell jq to replace variables mid JSON string?

Thanks.

Solution:

The issue seems to be that jq assumes data on stdin is formatted JSON data. This substitution actually only works on a "filter", which is jq's term for a script. Using the flags -n and -f [filter.json] to correctly state the input data is a filter, not actual data and using the \($var) syntax, as @peak pointed out works well.

example.json then could become example.jq:

{
  "title": "Where the \($color) Fern Grows"
}

Which when run, as they suggested:

jq -n --arg color "Red" -f example.jq

Works perfectly. The concept between data and filter is important and one I didn't realize. I thought it was all just interpolation and templating like most other programs. This seems to take more inspiration from awk where this is common however.

Fancy answered 28/8, 2022 at 16:50 Comment(3)
Not sure why you are replicating the answer as part of the Q, but in any case, note that the problem with your original approach is that jq expects JSON (or raw strings) on its STDIN, not a jq program. It has nothing to do with mangling. Perhaps you could adjust/moderate your commentary elsewhere accordingly.Supplemental
Ah I see so there is a difference between a jq filter (their words) and the data. Args only work on filtersFancy
And this is precicely why I restated your answer - to elaborate and make sure I understood it fully (which apparently I didnt)Fancy
S
2

For suggested ways to use jq as a template engine, see the jq Cookbook: https://github.com/stedolan/jq/wiki/Cookbook#using-jq-as-a-template-engine

In your case, it would probably be better to use the "interpolation" approach as per your original SO question: jq not replacing json value with parameter

example.jq:

{
  "title": "Where the \($color) Fern Grows"
}

Invocation:

jq -n --arg color Red -f example.jq

or:

jq --arg color Red . <(example.jq)

Otherwise ...

... you could use sub, though that might be brittle.

Supplemental answered 28/8, 2022 at 17:26 Comment(3)
Oh interesting, so it is exclusively a stdin issue? That's what you were hinting in that other question. Thanks for jumping over here and helping out.Fancy
The important distinction is between a jq program and its substrate (the data).Supplemental
Thank you for the help. This is helping me understand the core issue of difference in data types I was working with.Fancy

© 2022 - 2024 — McMap. All rights reserved.