124

I have a JSON output as follows:

{
  "example": {
    "sub-example": [
      {
        "name": "123-345",
        "tag" : 100
      },
      {
        "name": "234-456",
        "tag" : 100
      },
      {
        "name": "4a7-a07a5",
        "tag" : 100
      }
    ]
  }
}

I want to extract the values of the three "name" fields and store it in three variables.

I tried cat json_file | jq '.["example.sub-example.name"]' to extract the value of the "name" field but that doesn't work.

Can anyone tell me how to achieve this using jq (or some other method)?

hamza keurti
  • 385
  • 1
  • 2
  • 15
rmb
  • 1,737
  • 4
  • 14
  • 20

3 Answers3

139

If you just want to extract the name fields, the command you're looking for is jq '.example."sub-example" | .[] | .name'. If you want to keep the names in an array, wrap the whole jq expression in square brackets.

aaaaaa123456789
  • 5,541
  • 1
  • 20
  • 33
  • Thank you for your suggestion. However when I do cat test | jq '.example."sub-example" | .[] | .name' I get the error: error: syntax error, unexpected QQSTRING_START, expecting IDENT .example."sub-example" | .[] | .name ^ 1 compile error (with ^ pointing to the dot after jq '.example) – rmb Aug 30 '16 at 13:30
  • Are you using the latest version of `jq`? It worked just fine on my system. I'm using version 1.5 (you can check with `jq --version`). – aaaaaa123456789 Aug 30 '16 at 13:38
  • It is 1.3 (I downloaded it via apt-get install jq). Is there some other way to get the latest version?I am using Ubuntu 14.04 server. – rmb Aug 30 '16 at 13:44
  • If I have some field "name-of-instance" instead of "name", the command jq '.example."sub-example" | .[] | .name-of-instance' doesnt work. Do you have suggestions to fix it? – rmb Aug 30 '16 at 14:28
  • That's because it's interpreting `.name-of-instance` as an expression (`.name - of - instance`). Use quotes, like I did in `"sub-example"`. – aaaaaa123456789 Aug 30 '16 at 14:31
  • How do you extract two fields at a time? – Petrus Theron Nov 29 '18 at 12:25
  • @PetrusTheron Depends on how you want to extract them. If you want them in an object, for instance, you can just construct it: `.example."sub-example" | .[] | {field1: .field1, field2: .field2}`. – aaaaaa123456789 Nov 29 '18 at 21:02
46

Using jq 1.3 (and later), you can use the filter to extract the values:

.example["sub-example"] | .[] | .name

Or more compactly:

.example["sub-example"][].name

These of course also work with later versions of jq as well.

Reading into shell variables

Rather than populating separate shell variables (which would require knowing in advance how many values there are), consider populating a shell array. For example, using a bash shell with mapfile (aka readarray):

mapfile -t ary < <(< json_file jq '.example."sub-example"[].name')

You could alternatively use a shell while loop. Etc etc. There are many SO Qs on this topic.

peak
  • 105,803
  • 17
  • 152
  • 177
7

It's been a few years and I recently had to do this myself so thought I should post another way here.

You can also use map() to extract specific fields. e.g.

.example."sub-example"|map(.name)

Ref: https://jqplay.org/s/N6TboUkELM

Mandar Pathak
  • 839
  • 6
  • 17