I'm having the following dataset:
{
"data": {
"activeFindings": {
"findings": [
{
"findingId": "someFindingID#84209",
"products": [
"hostA.corp.somedomain.org",
"hostB.corp.somedomain.org"
],
"totalAffectedObjectsCount": 6
},
{
"findingId": "someFindingID#2145016",
"products": [
"hostC.corp.somedomain.org"
],
"totalAffectedObjectsCount": 1
},
{
"findingId": "someFindingID#67129",
"products": [
"hostD.corp.somedomain.org"
],
"totalAffectedObjectsCount": 4
},
{
"findingId": "someFindingID#67774",
"products": [
"hostA.corp.somedomain.org"
],
"totalAffectedObjectsCount": 6
}
]
}
}
}
The following command (though the first result returns null) will give the list of findingID and its associated host(s):
cat test | jq -r '.data[] | .. | "\(.findingId?) \(.products?)"'
null null
someFindingID#84209 ["hostA.corp.somedomain.org","hostB.corp.somedomain.org"]
someFindingID#2145016 ["hostC.corp.somedomain.org","hostE.corp.somedomain.org","hostG.corp.somedomain.org"]
someFindingID#67129 ["hostD.corp.somedomain.org"]
someFindingID#67774 ["hostA.corp.somedomain.org"]
What I'd like to achieve is to loop through each values and pass the findingId & products as arguments in a bash script.
The following:
someFindingID#84209 ["hostA.corp.somedomain.org","hostB.corp.somedomain.org"]
someFindingID#2145016 ["hostC.corp.somedomain.org","hostE.corp.somedomain.org","hostG.corp.somedomain.org"]
someFindingID#67129 ["hostD.corp.somedomain.org"]
someFindingID#67774 ["hostA.corp.somedomain.org"]
Would result in:
./somescript.sh someFindingID#84209 hostA.corp.somedomain.org
./somescript.sh someFindingID#84209 hostB.corp.somedomain.org
./somescript.sh someFindingID#2145016 hostC.corp.somedomain.org
./somescript.sh someFindingID#2145016 hostE.corp.somedomain.org
./somescript.sh someFindingID#2145016 hostG.corp.somedomain.org
./somescript.sh someFindingID#67129 hostD.corp.somedomain.org
[...]
Any help/guidance on how to achieve the above would be greatly appreciated!
Thanks,
CodePudding user response:
I'd go with something like this:
jq -r '.data[]
| ..
| objects
| select(has("findingId"))
| "./somescript.sh \"\(.findingId)\" " .products[]
'
You might also want to quote the "product" values as well.
Or consider using @sh
.
CodePudding user response:
Solution:
jq -r '
.data[][][] |
.products[] as $product |
@sh "./somescript.sh \( .findingId ) \( $product )"
'
First of all, .data[] | ..
returns way too many nodes.
.data[][][]
would work great here..data.activeFindings.findings[]
can used if you want to be more precise.
You ask how to loop, but you're already doing it: []
is used to loop over an array.
The catch is that you want to loop without changing the context (.
). To do that, we can use as
:
.products[] as $product
Finally, we want to avoid code injection bugs, so we'll use @sh "..."
. In the string literal that follows @sh
, all interpolated values are converted into proper shell string literals.
$ jq -rn '"foo bar" | @sh "cmd \( . )"'
cmd 'foo bar'
All together, we get the following program:
.data[][][] |
.products[] as $product |
@sh "./somescript.sh \( .findingId ) \( $product )"
Demo on jqplay