2

Is it possible to pass and use in jq a variable of type array?

jq --arg ips "${IPs[0]}" '.nodes.app.ip = $ips[0] | .nodes.data.ip = $ips[1]' nodes.json
3
  • You're showing an array of exactly two items. Is that degenerate case really all you want? Commented Oct 15, 2019 at 17:25
  • Also, do you need only the easy case where no array element can contain a literal newline? Commented Oct 15, 2019 at 17:26
  • @CharlesDuffy of course not, it’s just for example Commented Oct 15, 2019 at 18:43

1 Answer 1

3

The general case solution is to pass that array in on stdin with NUL delimiters:

IPs=( 1.2.3.4 5.6.7.8 )
original_doc='{"nodes": { "app": {}, "data": {} }}'

jq -Rn --argjson original_doc "$original_doc" '
  input | split("\u0000") as $ips
  | $original_doc
  | .nodes.app.ip = $ips[0]
  | .nodes.data.ip = $ips[1]
' < <(printf '%s\0' "${IPs[@]}")

...emits as output:

{
  "nodes": {
    "app": {
      "ip": "1.2.3.4"
    },
    "data": {
      "ip": "5.6.7.8"
    }
  }
}

This is overkill for an array of IP addresses, but it works in the general case, even for actively-hostile arrays (ones with literal quotes, literal newlines, and other data that's intentionally hard-to-parse).


If you want to keep stdin clean, you can use a second copy of jq to convert your array to JSON:

IPs=( 1.2.3.4 5.6.7.8 )
IPs_json=$(jq -Rns 'input | split("\u0000")' < <(printf '%s\0' "${IPs[@]}"))

jq --argjson ips "$IPs_json" '
    .nodes.app.ip = $ips[0]
  | .nodes.data.ip = $ips[1]
' <<<'{"nodes": { "app": {}, "data": {} }}'
Sign up to request clarification or add additional context in comments.

1 Comment

Its working locally, but when I'm sending it via ssh jq doesn't work properly... stackoverflow.com/questions/58428131/…

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.