jq: error: syntax error, unexpected IDENT, expecting $end (Unix shell quoting issues?) at <top-level> - shell

cat explorer/connection-profile/test-network.json | jq ".organizations.Org1MSP.adminPrivateKey.path |= 44ab"
jq: error: syntax error, unexpected IDENT, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.organizations.Org1MSP.adminPrivateKey.path|=44ab
jq: 1 compile error
but it works fine with
cat explorer/connection-profile/test-network.json | jq ".organizations.Org1MSP.adminPrivateKey.path |= 44"
Why?
Actually I am trying to use
cat explorer/connection-profile/test-network.json | jq ".organizations.Org1MSP.adminPrivateKey.path |= ${PRIV_KEY}"
where the ${PRIV_KEY} is 44ab..._sk

You can assign a string to a variable that can be used inside a jq filter:
PRIV_KEY="44ab..._sk"
jq --arg path "$PRIV_KEY" '.organizations.Org1MSP.adminPrivateKey.path |= $path' explorer/connection-profile/test-network.json
This method is safer than trying to embed an expanded shell variable directly in the filter string because jq will properly handle arbitrary values instead of choking on things like quotes (Or their absence).
Note that jq takes filenames as arguments after the filter expression; no need for cat here (Unless that's standing in for curl or something, of course, and you're not using an existing file)

did you try this , i fixed the same error by setting the expression between '' and the values between ""
cat explorer/connection-profile/test-network.json | jq '.organizations.Org1MSP.adminPrivateKey.path |= "44ab"'

Related

bash filename as parameter in jq commands

Here is the bash function to parse a json file use 'jq' command:
jq_fullpath_endkey() {
PATHARRAY=$(jq -c 'paths | select(.[-1] == "'$keyword'")|map(strings |= ".\(.)" | numbers |= "[\(.)]") | join("")' **${news.json}**)
}
The news.json is the json file that contains all the content I'd like to parse with jq.
The function works once I replace ${news.json} with a variable named response which contains news.json content as string.
Below is the command which works:
PATHARRAY=$(jq -c 'paths | select(.[-1] == "'$keyword'")|map(strings |= ".\(.)" | numbers |= "[\(.)]") | join("")'**<<< "$response"**)
My question is how can I use 'json file' as part of the jq cmd ?
I suspect there is something wrong with double/single quote I am using.
I figure it out with "parameter substitution" in bash
myfile="news.json"
PATHARRAY=$(jq -c 'paths | select(.[-1] == "'$keyword'")|map(strings |= ".\(.)" | numbers |= "[\(.)]") | join("")' ${myfile})
Related concepts:
variable substitution
command substitution

How to pass environment bash variables into json using jq [duplicate]

I want to populate json template with value "Hello Jack", but the "Hello" part shall remain inside of template, is there are any way of doing that, I've tried code below but it gives me error:
jq -n --arg person "Jack" '{my_key: "Hello "$person}'
jq: error: syntax error, unexpected '$', expecting '}' (Unix shell quoting issues?) at <top-level>, line 1:
Use string interpolation syntax like so:
jq -n --arg person Jack '{my_key: "Hello \($person)"}'
And to load the template from a file, use the -f switch:
$ cat template.json
{
"my_key": "Hello \($person)"
}
$ jq -n --arg person Jack -f template.json
{
"my_key": "Hello Jack"
}

Not able to get value from json using jq when I replace one of the elements with variable

Using jq if I try to get the value of an element using string I am able to get the value. But to make it flexible if I replace it with a variable then it throws error.
data=$(cat <<EOF
{
"my_db_instance_class": {
"sensitive": false,
"type": "string",
"value": "db.t3.medium"
},
"my_db_instance_test": {
"sensitive": false,
"type": "string",
"value": "db.t4.medium"
}
}
EOF
)
#echo $data
keys=$(echo $data | jq -r '. |=keys' | jq '.[]')
#echo $keys
for key in $keys
do
value=$(echo $data | jq --arg k "$key" '.my_db_instance_class.value')
final_value="${final_value}${key}: ${value}"
done
The above code works but it not very static. Below I have replaced my_db_instance_class with a variable
for key in $keys
do
value=$(echo $data | jq --arg k "$key" '.$k.value')
final_value="${final_value}${key}: ${value}"
done
Error message
jq: error: syntax error, unexpected '$' (Unix shell quoting issues?) at <top-level>, line 1:
.$k.value
jq: error: try .["field"] instead of .field for unusually named fields at <top-level>, line 1:
.$k.value
jq: 2 compile errors
jq: error: syntax error, unexpected '$' (Unix shell quoting issues?) at <top-level>, line 1:
.$k.value
jq: error: try .["field"] instead of .field for unusually named fields at <top-level>, line 1:
.$k.value
jq: 2 compile errors
Expected final output of the whole script
"my_db_instance_class": "db.t3.medium""my_db_instance_test":
"db.t3.medium"
It seems like you're first trying to get all the keys, then loop over then to show the key with the relevant value.
We can simplify this using just jq like so:
to_entries[] | "\(.key): \(.value.value)"
This will produce the following output:
my_db_instance_class: db.t3.medium
my_db_instance_test: db.t4.medium
JqPlay Demo
to_entires documentation
String interpolation (\()) documentation

Passing Environment variables to a jq command [duplicate]

I am trying to use jq to construct a hash in which a key name comes from a variable. Something like this:
jq --null-input --arg key foobar '{$key: "value"}'
This doesn't work, however, and gives the following error:
error: syntax error, unexpected '$'
{$key: "value"} 1 compile error
Use parentheses to evaluate $key early as in:
jq --null-input --arg key foobar '{($key): "value"}'
See also: Parentheses in JQ for .key
You can also use String interpolation in jq which is of the form "\(..)". Inside the string, you can put an expression inside parens after a backslash. Whatever the expression returns will be interpolated into the string.
You can do below. The contents of the variable key is expanded and returned as a string by the interpolation sequence.
jq --null-input --arg key foobar '{ "\($key)": "value"}'

jq and bash: object construction with --arg is not working

Given the following input:
J='{"a":1,"b":10,"c":100}
{"a":2,"b":20,"c":200}
{"a":3,"b":30,"c":300}'
The command
SELECT='a,b'; echo $J | jq -c -s --arg P1 $SELECT '.[]|{a,b}'
produces
{"a":1,"b":10}
{"a":2,"b":20}
{"a":3,"b":30}
but this command produces unexpected results:
SELECT='a,b'; echo $J | jq -c -s --arg P1 $SELECT '.[]|{$P1}'
{"P1":"a,b"}
{"P1":"a,b"}
{"P1":"a,b"}
How does one get jq to treat an arg string literally?
Using tostring gives an error
SELECT='a,b'; echo $J | jq -c -s --arg P1 $SELECT '.[]|{$P1|tostring}'
jq: error: syntax error, unexpected '|', expecting '}' (Unix shell quoting
issues?) at <top-level>, line 1:
.[]|{$SELECT|tostring}
jq: 1 compile error
SELECT needs to be a variable and not hardcoded in the script.
SELECT needs to be a variable and not hardcoded in the script.
Assuming you want to avoid the risks of "code injection" and that you want the shell variable SELECT to be a simple string such as "a,b", then consider this reduce-free solution along the lines you were attempting:
J='{"a":1,"b":10,"c":100}'
SELECT='a,b'
echo "$J" |
jq -c --arg P1 "$SELECT" '
. as $in | $P1 | split(",") | map( {(.): $in[.]} ) | add'
Output:
{"a":1,"b":10}
If you really want your data to be parsed as syntax...
This is not an appropriate use case for --arg. Instead, substitute into the code:
select='a,b'; jq -c -s '.[]|{'"$select"'}' <<<"$j"
Note that this has all the usual caveats of code injection: If the input is uncontrolled, the output (or other behavior of the script, particularly if jq gains more capable I/O features in the future) should be considered likewise.
If you want to split the literal string into a list of keys...
Here, we take your select_str (of the form a,b), and generate a map: {'a': 'a', 'b': 'b'}; then, we can break each data item into entries, select only the items in the map, and there's our output.
jq --arg select_str "$select" '
($select_str
| split(",")
| reduce .[] as $item ({}; .[$item]=$item)) as $select_map
| with_entries(select($select_map[.key]))' <<<"$j"

Resources