bash/shell jq parse to variable from aws json [duplicate] - json

This question already has answers here:
filtering data using parameters
(2 answers)
Closed 7 years ago.
I am trying to parse json result from aws result, but I getting error or null when I am using $ip, when I am using specific IP it work. something wrong when I am using tne variable inside the jq command
#!/bin/bash
aws ec2 describe-addresses --region eu-west-1 > 1.txt
ipList=( "52.16.121.238" "52.17.250.188" )
for ip in "${ipList[#]}";
do
echo $ip
cat 1.txt | jq '.Addresses | .[] | select (.PublicIp==$ip) | .InstanceId'
#echo $result
done
Please advise.

You're using single quotes around your jq program, which is causing the shell variable to not be interpolated. Furthermore, even if it were, you would still need to add string quoting around the variable interpolation to make jq interpret it as a string literal. Since doing shell variable interpolation into jq programs is hard and error-prone, jq provides a command-line argument to this effect, --arg, intended to lift shell variables into jq variables. Your jq invocation would therefore look like this:
jq --arg ip "$ip" '.Addresses[] | select(.PublicIp == $ip) | .InstanceId'

Thanks for your help. the right format is:
cat 1.txt | jq ".Addresses | .[] | select(.PublicIp==\"$ip\") | .InstanceId"

Related

How to use jq to extract a particular field from a terraform plan to show resources that are updated or changed?

I just want to be able to have a small quick view or list of what is changing with a terraform plan instead of the long output given by a terraform plan.
So far I think it can be done with a terraform plan and jq.
Here is what I have so far -
I run a plan like this:
terraform plan -out=tfplan -no-color -detailed-exitcode
Then I am trying to use jq to get the changes or updates using this:
terraform show -json tfplan | jq '.resource_changes[]
| select( .change.actions
| contains("create") or contains("update") )'
It gives me the error :
jq: error (at <stdin>:1): array (["no-op"]) and string ("create")
cannot have their containment checked
My jq skills are not the best - can anyone update my jq to work or is there an alternative way to do this?
contains checks if one array is a subarray of the other, recursively (substrings are matched too; note the "d" in "create" vs "created"):
$ jq -n '["created"] | contains(["create"])'
true
You can use the SQL-style IN filter:
$ jq -n '"create" | IN("created", "foo")'
false
$ jq -n '"created" | IN("created", "bar")'
true
So for your concrete use case you would probably want something like the following:
terraform show -json tfplan | jq '
.resource_changes[]
| select(
.change.actions as $actions
| "create" | IN($actions[])
or "update" | IN($actions[]))'
Or using any/2:
terraform show -json tfplan | jq '
.resource_changes[]
| select(any(.change.actions[]; .=="create" or .=="update"))'

How to add bash variable to json file? [duplicate]

This question already has answers here:
Modify a key-value in a json using jq in-place
(8 answers)
Closed 1 year ago.
I have a daemon.json file which contains one line as below
{ "insecure-registries":["192.X.X.X:8123"] }
I am trying to use a variable to change generically to the current IP address. In bash script normally
I'd store in a variable like
myip=hostname -I | awk '{print $1}'
{ "insecure-registries":["$myip:8123"] }
How to use a kind of variable in JSON file?
If you have access to jq, I would recommend storing not JSON, but a jq filter, like
{"insecure-registries": ["\($ip):8123"]}
Assume the preceding is in file named foo.jq; then using jq as follows to produce JSON from the filter.
$ myip=$(hostname -I | awk '{print $1}') # 192.0.2.42, e.g.
$ jq -nf foo.jq --arg ip "$myip"
{
"insecure-registries": [
"192.0.2.42:8123"
]
}
JSON itself doesn't have a notion of substitution, and bash itself isn't really suitable for making substitutions like this.

For each item in an array using jq [duplicate]

This question already has an answer here:
getting all the values of an array with jq
(1 answer)
Closed 3 years ago.
Say I have this command:
kbc get pods -o=json | jq -c
which gives me something like:
{"apiVersion":"v1","items":[{"name":"a"},{"name":"b"},{"name":"c"}]}
how can I echo the name for each element in the items array? Something like this:
kbc get pods -o=json | jq -c | jq '.items[].name' | cat
kbc get pods -o=json | jq -r '.items[].name'
Using -r tells jq to write raw output, thus without quoting the names as JSON strings.

Rewriting a JSON file into a CSV efficiently in Bash [duplicate]

This question already has answers here:
Use jq to Convert json File to csv
(1 answer)
Converting json map to csv using jq
(3 answers)
Closed 4 years ago.
I want to efficiently rewrite a large json, which has always the same field names, into a csv, ignoring its keys.
To give a concrete example, here is a large JSON file (tempST.json):
https://gist.githubusercontent.com/pedro-roberto/b81672a89368bc8674dae21af3173e68/raw/e4afc62b9aa3092c8722cdbc4b4b4b6d5bbc1b4b/tempST.json
If I rewrite just fields time, ancestorcount and descendantcount from this JSON into a CSV I should get:
1535995526,1,1
1535974524,1,1
1535974528,1,2
...
1535997274,1,1
The following script tempSpeedTest.sh writes the value of the fields time, ancestorcount and descendantcount into each line of the csv:
rm tempOutput.csv
jq -c '.[]' < tempST.json | while read line; do
descendantcount=$(echo $line | jq '.descendantcount')
ancestorcount=$(echo $line | jq '.ancestorcount')
time=$(echo $line | jq '.time')
echo "${time},${ancestorcount},${descendantcount}" >> tempOutput.csv
done
However the script takes around 3 minutes to run, which is unsatisfying:
>time bash tempSpeedTest.sh
real 2m50.254s
user 2m43.128s
sys 0m34.811s
What is a faster way to achieve the same result?
jq -r '.[] | [.time, .descendantcount, .ancestorcount] | #csv' <tempST.json >tempOutput.csv
See this running at https://jqplay.org/s/QJz5FCmuc9

Extract value of json-like variable in bash [duplicate]

This question already has answers here:
Parsing JSON with Unix tools
(45 answers)
Closed 4 years ago.
I have a variable in bash that is an output of Amazon EMR create command;
CLUSTER=$(aws emr create-cluster ...)
echo $CLUSTER
the output is like this:
{ "ClusterId": "j-9YWMBYN98LN7" }
What I need to do is to extract the value j-9YWMBYN98LN7 to a new variable, something like:
ID=$CLUSTER.(ClusterId)
Of course the above command doesn't work. I have tried with jq but no luck.
ID=$(jq -r '.ClusterId' $CLUSTER)
The thing is I'm not even sure what type $CLUSTER is. How do I extract the value j-9YWMBYN98LN7 there? Thanks
If you want to use jq, you can do it this way
ID=`echo ${CLUSTER} | jq -r '.ClusterId'`
If
echo $CLUSTER
gives you
{ "ClusterId": "j-9YWMBYN98LN7" }
then
ID=$(awk 'BEGIN{FS="\""}{print $4}' <<< "${CLUSTER}")
should do it.
echo "$ID"
j-9YWMBYN98LN7
Try the following:
ID=$(echo "${CLUSTER}" | sed 's/{ "ClusterId": "//' | sed 's/" }//')
That will isolate j-9YWMBYN98LN7, or whatever is between the last set of quotes, into the variable $ID.
I get the feeling there is more to what you need as you are probably planning on using the contents of $ID for something and there may be more efficient ways to capture that value for you. Maybe if you can explain a bit more how you plan on using the value we can provide even more actionable answers.