2

We have the following example file ( very long file , this is short example )

"request_status" : "FAILED"
{
    "href" : "http://localhost:8080/api/v1/clusters/sys41/requests/333",
    "Requests" : {
        "cluster_name" : "sys41",
        "id" : 333,
        "request_status" : "COMPLETED"
    }
},
{
    "href" : "http://localhost:8080/api/v1/clusters/sys41/requests/334",
    "Requests" : {
        "cluster_name" : "sys41",
        "id" : 334,
        "request_status" : "FAILED"
    }
},
{
    "href" : "http://localhost:8080/api/v1/clusters/sys41/requests/335",
    "Requests" : {
        "cluster_name" : "sys41",
        "id" : 335,
        "request_status" : "FAILED"
    }
},
{
    "href" : "http://localhost:8080/api/v1/clusters/sys41/requests/336",
    "Requests" : {
        "cluster_name" : "sys41",
        "id" : 336,
        "request_status" : "COMPLETED"
    }
}

how to print the line after the line that matches "id" : $num
e.g. for

num=335 

how to get the line after

"id" : $num

Expected output

"request_status" : "FAILED"
  • 3
    This looks like a job for jq which is the tool specifically built for querying JSON objects, but I am not fluent enough to impart unto you the correct incantation. – DopeGhoti Mar 5 '18 at 17:16
  • 1
    Could you please post a less broken JSON file? It's difficult to come up with a proper jq solution when the JSON is so severely mangled at the top. – Kusalananda Mar 5 '18 at 17:40
  • 1
    If it's really json you're dealing with, then be careful using solutions that assume a fixed number of spaces around the colons (and all the other flexible parts of the json spec!) – Jeff Schaller Mar 5 '18 at 17:44
1

Given the shell variable num set equal to 335:

grep -A1 "\"id\" : $num," /path/to/file

I get a lot of mileage out of grep's handy -A, -B, and -C options, the mnemonics for which I use are "After", "Before", and "Context".

  • grep -A n 'pattern' file will show the n lines After a pattern match, in addition to the matching line itself.

  • grep -C n 'pattern' file will show the n lines Before a pattern match, in addition to the matching line itself.

  • grep -C n 'pattern' file will show the n lines both before and after (i. e. the Context of) a pattern match, in addition to the matching line itself.

  • For less toothpicks: grep -A1 '"id" : '"$num," ... – Kusalananda Mar 5 '18 at 18:50
  • 1
    Just as many toothpicks; they're just shorter (: – DopeGhoti Mar 5 '18 at 18:55
6

Assuming that the JSON file is one big array of objects such as

  {
    "href": "http://localhost:8080/api/v1/clusters/sys41/requests/333",
    "Requests": { "id": 333, "cluster_name": "sys41", "request_status": "COMPLETED" }
  },

(noting that newlines are not significant, and neither is the ordering of the keys in an object) then, the following jq command would get the request_status entry for the id corresponding to $num:

$ num=355
$ jq -r ".[].Requests | select(.id == $num).request_status" file.json
FAILED

It does this by picking out all the Requests entries from each object and filtering them on the id. For the ones that pass the filter, it extracts request_status.

The -r option to jq makes it output raw data instead of JSON (FAILED would have been double quoted without it).


Bonus material:

$ jq -r '.[].Requests | "\(.id): \(.request_status)"' file.json
333: COMPLETED
334: FAILED
335: FAILED
336: COMPLETED
  • 2
    jq is the right tool for the job. – Zachary Brady Mar 5 '18 at 18:36
1
awk '/"id" : 335/{getline;print}'

or

var="\"id\" : 335"
awk "/$var/{getline;print}"

or

awk -v var="\"id\" : 335" '$0~var{getline;print}'

or

var="\"id\" : 335"
awk -v var="$var" '$0~var{getline;print}'

or any of the above, but without needing the "id" : " part of the string, in the form:

awk -v var="335" '$0~"id" : var{getline;print}'
  • May not work as intended. For example, will show a false match for "id" : 1355. – DopeGhoti Mar 5 '18 at 17:24
  • Did you try that and have it fail? – user1404316 Mar 5 '18 at 17:27
  • Oh, I see - you mean that I just pulled the rong text for the search. That's easy to replace. – user1404316 Mar 5 '18 at 17:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.