1

I am wanting to pipe values into a bash script that will change values in a json file using jq. I've been working on this for a while now and I can't get past the first set of errors.

Here is my simple json file:

{
    "0000000": {
        "pogo": "AJHVUYKJBOIHKNNLNM"
    },
    "7000000": {
        "pogo": "PPPVUYKJBOIHKNNLNM"
    }
}

Here is my script

#!/bin/bash

#-- pass into script
pgid="${1}"
tpogo="${2}"
file="file.json"

#-- tmp files
tmp_dir="$(mktemp -d -t 'text.XXXXX' || mktemp -d 2>/dev/null)"
tmp_input1="${tmp_dir}/temp_input1.txt"

if [ ! -n "$2" ]; then
   { echo "Check your command as you are missing a variable ..."; echo "Example: script.sh "00000001" "jvkkjbkjbd" ..."; }
   exit 1;
fi

jq -r ".${pgid}.pogo = \"${tpogo}\"" "$file" > "$tmp_input1"
cat "$tmp_input1"
rm -rf "$tmp_dir"

Here are the errors:

jq: error: Invalid numeric literal at EOF at line 1, column 9 (while parsing '.0000000.') at <top-level>, line 1:
.0000000.pogo = "XXXXXXX"
jq: error: syntax error, unexpected IDENT, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.0000000.pogo = "XXXXXXX"
jq: 2 compile errors

I have tried so many variations from stack and most of them look similar to what I am doing now.

Vituvo
  • 1,008
  • 1
  • 9
  • 29
  • Parts of this are duplicative of [How to use `jq` for a query where key is a numeric string](https://stackoverflow.com/questions/52460453/how-to-use-jq-for-a-query-where-key-is-a-numeric-string/52460866#52460866). – Charles Duffy Sep 28 '18 at 21:23
  • @Barmar I did so mate. Surely appreciate the help. – Vituvo Sep 28 '18 at 21:32

1 Answers1

6

As for the immediate issue: .key works with { "foo": "value" }, but .100 doesn't work with { "100": "value" }; the syntax you're relying is sugar, only available for a limited subset of keys. .["100"] would work, but generating that by expanding shell variables into strings parsed as code is fragile (jq isn't a side-effecting language as of current releases, but in languages that do support I/O operations, such substitutions can be leveraged for injection attacks). To do things the Right Way, pass your variables out-of-band from your code, and use them for lookups in a manner that doesn't rely on what they contain.


The jq equivalent to awk's -v var="$value" is --arg var "$value", used thusly:

jq --arg pgid "$pgid" \
   --arg tpogo "$tpogo" \
   '.[$pgid].pogo = $tpogo'

Testing this with your data:

json='{"0000000":{"pogo":"AJHVUYKJBOIHKNNLNM"},"7000000":{"pogo":"PPPVUYKJBOIHKNNLNM"}}'
pgid="0000000"
tpogo="XXXXXXX"

jq --arg pgid "$pgid" --arg tpogo "$tpogo" \
   '.[$pgid].pogo = $tpogo' <<<"$json"

...emits as output:

{
  "0000000": {
    "pogo": "XXXXXXX"
  },
  "7000000": {
    "pogo": "PPPVUYKJBOIHKNNLNM"
  }
}
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • I did see that but It did not make much sense to me at the time, but now it does. Also .. is it necessary to line break your command? – Vituvo Sep 28 '18 at 21:37