four43
four43

Reputation: 1750

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

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.

Upvotes: 1

Views: 2917

Answers (1)

peak
peak

Reputation: 116870

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.

Upvotes: 3

Related Questions