user1578872
user1578872

Reputation: 9078

JQ JSON select with dynamic shell param

I use JQ for JSON formatting and filtering the data.

sed "s/.*Service - //p" tes.log | jq 'if (.requests | length) != 0 then .requests |= map(select(.orderId == "2260")) else "NO"  end' > ~/result.log

Here, the orderid is been hardcoded to 2260. But my requirement is to make it parameter driven.

So I store the param to a variable called ORDER_ID like,

ORDER_ID=2260

and then using $ORDER_ID, but it doesnt work.

sed "s/.*Service - //p" tes.log | jq 'if (.requests | length) != 0 then .requests |= map(select(.orderId == "$ORDER_ID")) else "NO"  end' > ~/result.log

It is not replacing the $ORDER_ID with the passed param.

Thanks

Upvotes: 0

Views: 835

Answers (2)

jq170727
jq170727

Reputation: 14695

As the following bash script demonstrates, Stephen Gildea's example will not work because jq does not allow use of ' single quotes.

#!/bin/bash
ORDER_ID=2260

jq "if (.requests | length) != 0 then .requests |= map(select(.orderId == '$ORDER_ID')) else 'NO' end" <<EOF
{"requests":[{"orderId":2260}]}
EOF

Specifically the 'NO' literal will generate a syntax error:

jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at <top-level>, line 1:
if (.requests | length) != 0 then .requests |= map(select(.orderId == '2260')) else 'NO' end                                                                      
jq: error: Possibly unterminated 'if' statement at <top-level>, line 1:
if (.requests | length) != 0 then .requests |= map(select(.orderId == '2260')) else 'NO' end
jq: 2 compile errors

One approach which will work is to use the --argjson option, use single quotes for the entire jq filter and double quotes for strings literals within the filter. E.g.

jq --argjson ORDER_ID "$ORDER_ID" '
if (.requests|length)!=0 then .requests |= map(select(.orderId == $ORDER_ID)) else "NO" end
'

Upvotes: 0

Stephen Gildea
Stephen Gildea

Reputation: 385

The shell does not expand variables inside single quotes. If jq is agnostic about the quote type, try swapping double and single quotes throughout. Also, if you want to select only the line with Service - in it, you need the -n flag for sed:

sed -n 's/.*Service - //p' tes.log | jq "if (.requests | length) != 0 then .requests |= map(select(.orderId == '$ORDER_ID')) else 'NO' end" > ~/result.log

Upvotes: 1

Related Questions