2

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".

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

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.

1

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
  • Why don't grep directly, like grep -q '"state": *"tiling"'? – cuonglm Feb 24 '16 at 6:29
1

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

jshon -e client -e state -u < file             
floating
0

another easy alternative to extract info from JSON and test it is jtc tool (assuming source json is in file.json):

bash $ cat file.json | jtc -w "[state]:<tiling>" | grep "tiling" >/dev/null; if [ $? == 0 ]; then echo "true"; else echo "false"; fi;
false
bash $ 
bash $ cat file.json | jtc -w "[state]:<floating>" | grep "floating" >/dev/null; if [ $? == 0 ]; then echo "true"; else echo "false"; fi;
true
bash $ 

Your Answer

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