I have a json file:
{
"rec_9M":
{
"id":"000",
"rec_E":
[
{
"id":"111"
} ,
{
"id":"222"
}
]
}
}
I need to change values rec_9M.rec_E[].id but I need to use a universal bash function for that, which can be using for changing values on different levels (rec_9M.id or rec_9M.rec_E[].files[].id)
I tryed:
VAR=rec_9M.rec_E[]
NUM=555
echo $(cat config.json) | jq --arg VAR_I $VAR --arg NUM_I $NUM '.[$VAR_I].id = $NUM_I' > config_t.json
cat config_t.json
Expect: enter image description here
{
"rec_9M": {
"id": "000",
"rec_E": [
{
"id": "555"
},
{
"id": "555"
}
]
}
}
Reality: enter image description here
{
"rec_9M": {
"id": "000",
"rec_E": [
{
"id": "111"
},
{
"id": "222"
}
]
},
"rec_9M.rec_E[]": {
"id": "555"
}
}
If key was hardcoded - everything works correctly.:
echo $(cat config.json) | jq --arg VAR_I $VAR --arg NUM_I $NUM '.rec_9M.rec_E[].id = $NUM_I' > config_t.json
Also I tryed any combinations of using VAR_I in jq with quotes and special symbols, for example "($VAR_I)". Results are the same or jq parsing errors.
Maybe anybody know a solution?
One way uses getpath()
to extract the paths of the input JSON based on a variable (Or other string):
$ jq --arg path "rec_9M.rec_E" --arg i 555 'getpath($path | split("."))[] += {id: $i}' config.json
{
"rec_9M": {
"id": "000",
"rec_E": [
{
"id": "555"
},
{
"id": "555"
}
]
}
}
Note leaving the trailing []
off the path; this only works with paths through object elements that end in an array of objects.
Another, more flexible but also more fragile approach involves putting the path held in the shell variable directly in the jq
program:
$ path_var=".rec_9M.rec_E[].id"
$ jq --arg i 555 "$path_var"' |= $i' config.json
{
"rec_9M": {
"id": "000",
"rec_E": [
{
"id": "555"
},
{
"id": "555"
}
]
}
}
Note having to put a leading .
in the path expression.
echo $(cat config.json)
has so many things wrong with it. jq
takes the file names of JSON documents as arguments; use that. Or even a Useless Use of Cat like cat config.json | jq ...
for example purposes is fine if you intend to replace the cat
part with something more complex like a curl
request or other command that outputs JSON... but don't combine it with echo
. Besides introducing needless steps, if your shell's version of echo
does things like replace \n
with a literal newline, it's going to break everything else if escape sequences are present in strings in the JSON.