Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For example, here is my program's output (bspwm, if you wanted to know):

{
  "id": 29360131,
  "splitType": "vertical",
  "splitRatio": 0.5,
  "birthRotation": 90,
  "vacant": true,
  "sticky": false,
  "private": false,
  "locked": false,
  "presel": null,
  "rectangle": {
    "x": 0,
    "y": 0,
    "width": 1920,
    "height": 1200
  },
  "firstChild": null,
  "secondChild": null,
  "client": {
    "className": "Termite",
    "instanceName": "termite",
    "borderWidth": 1,
    "state": "floating",
    "lastState": "tiled",
    "layer": "normal",
    "lastLayer": "normal",
    "urgent": false,
    "visible": true,
    "icccmFocus": true,
    "icccmInput": true,
    "minWidth": 10,
    "maxWidth": 0,
    "minHeight": 19,
    "maxHeight": 0,
    "wmStatesCount": 0,
    "wmState": [],
    "tiledRectangle": {
      "x": 0,
      "y": 0,
      "width": 958,
      "height": 1198
    },
    "floatingRectangle": {
      "x": 638,
      "y": 394,
      "width": 642,
      "height": 410
    }
  }
}

I want to check if "state" is not "tiling". In this case, it is "floating".

share|improve this question
    
If str is the long string you present, then: echo "$str" | grep -oP '"state":"\K([^"]*)' – BinaryZebra Feb 24 at 6:02
    
<your program> | grep -q '"state": *"tiling"' || echo not tiling` Or use a json parser like jq. – cuonglm Feb 24 at 6:22

Using jq with Boolean Tests

Given that your JSON is stored in a variable named json, you could do the following at the shell prompt:

$ echo "$json" | jq '.client.state | test("tiling")'
false

This correctly returns false because your corpus contains the value floating instead.

Negating Tests

Alternatively, if you wanted to test that the value is not tiling, you can use the | not filter to negate the logic of your test. For example:

$ echo "$json" | jq '.client.state | test("tiling") | not'
true

This correctly returns true because the client state isn't tiling, it's floating.

Extracting the Value

In case you want to make sure your filters are working in a sane way, you can also use jq to parse out the value for that nested key. For example:

$ echo "$json" | jq .client.state
"floating"

You can then use that information to validate your tests and filters, or simply pass it along a shell pipeline to fgrep or fgrep -v if you don't mind spawning an additional process.

share|improve this answer

Better option is to use a JSON parser.

If you insist on using grep:

Assuming your grep supports PCRE (-P):

bspwm | grep -Po '"state":\K[^,]*'

This will get the value (with quotes) of the key "state".

If you don't want surrounding quotes around the key:

bspwm | grep -Po '"state":"\K[^"]*'

For example:

% grep -Po '"state":\K[^,]*' <<<'{"id":29360131,"splitType":"vertical","splitRatio":0.500000,"birthRotation":90,"vacant":true,"sticky":false,"private":false,"locked":false,"presel":null,"rectangle":{"x":0,"y":0,"width":1920,"height":1200},"firstChild":null,"secondChild":null,"client":{"className":"Termite","instanceName":"termite","borderWidth":1,"state":"floating","lastState":"tiled","layer":"normal","lastLayer":"normal","urgent":false,"visible":true,"icccmFocus":true,"icccmInput":true,"minWidth":10,"maxWidth":0,"minHeight":19,"maxHeight":0,"wmStatesCount":0,"wmState":[],"tiledRectangle":{"x":0,"y":0,"width":958,"height":1198},"floatingRectangle":{"x":638,"y":394,"width":642,"height":410}}'

"floating"


% grep -Po '"state":"\K[^"]*' <<<'{"id":29360131,"splitType":"vertical","splitRatio":0.500000,"birthRotation":90,"vacant":true,"sticky":false,"private":false,"locked":false,"presel":null,"rectangle":{"x":0,"y":0,"width":1920,"height":1200},"firstChild":null,"secondChild":null,"client":{"className":"Termite","instanceName":"termite","borderWidth":1,"state":"floating","lastState":"tiled","layer":"normal","lastLayer":"normal","urgent":false,"visible":true,"icccmFocus":true,"icccmInput":true,"minWidth":10,"maxWidth":0,"minHeight":19,"maxHeight":0,"wmStatesCount":0,"wmState":[],"tiledRectangle":{"x":0,"y":0,"width":958,"height":1198},"floatingRectangle":{"x":638,"y":394,"width":642,"height":410}}'

floating
share|improve this answer
    
Why don't grep directly, like grep -q '"state": *"tiling"'? – cuonglm Feb 24 at 6:29

Using a dedicated JSON parser, like Jshon, is a more robust approach:

jshon -e client -e state -u < file             
floating
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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