Reputation: 107
I have a file with the following format:
{
"files":[
{
"BLOCK1":{
"SUBBLOCK1":{
"akey1":"avalue1",
"bkey1":"bvalue1",
"ckey1":"cvalue1"
},
"dkey1":"dvalue1",
"key":"evalue1"
}
},
{
"BLOCK-2":{
"SUBBLOCK2":{
"akey2":"avalue2",
"bkey2":"bvalue2"
},
"ckey2":"cvalue2",
"key":"dvalue2"
}
},
{
"BLOCK-A":{
"SUBBLOCKA":{
"akeyA":"avalueA",
"bkeyA":"bvalueA"
},
"ckeyA":"cvalueA",
"key":"dvalueA"
}
}],
"NOBLOCK":"value",
"key":"NOBLOCKvalue"
}
I'm using the following the jq statement to isolate "bvalueA":
value=$(jq -r '.files | .[2] | .["BLOCK-A"].SUBBLOCKA.bkeyA' jqtest)
Which works just fine. But the file changes order every night. So BLOCK-A might be element 0 one night, 1 the next, so on and so forth. How can I modify jq to always drill down to BLOCK-A no matter which element in the array it is?
Upvotes: 0
Views: 536
Reputation: 116780
This might be the least-keystrokes solution:
.files[]."BLOCK-A"//empty|.SUBBLOCKA.bkeyA
If there is a possibility that there is more than one "BLOCK-A" element, and if you want to ensure that all but the first will be ignored when that is the case, then you could wrap the above in a call to first/1
, assuming your version of jq has it: first( ... )
Using first
in this manner also yields a more efficient solution.
Upvotes: 2
Reputation: 14665
Here is an solution based on my previous answer to your earlier question:
$ jq -M '
def getfile($k): .files[] | select(keys[] == $k) | .[$k];
getfile("BLOCK-A").SUBBLOCKA.bkeyA
' jqtest
With the sample data provided the output is:
"bvalueA"
Upvotes: 0
Reputation: 92854
The alternative approach with has()
function:
jq -r '.files[] | if (has("BLOCK-A")) then .["BLOCK-A"].SUBBLOCKA.bkeyA else empty end' jqtest
bvalueA
Upvotes: 0