Table of Content
- Catch undefined keys and exit with 1
- Outputs without quotes
- Outputs full result into one line
- Outputs full each result
- Outputs each result into one line with given vaules
- Sorting by values
- Filter by values
- Use Value as Key
- Merge
- Variables
Catch undefined keys and exit with 1
{
"action": "do_something",
"condition1": "42",
"condition2": true
}
$ jq -n -c 'input | if .condition3 then .condition3 else null | halt_error(1) end' <<<"${my_json_variable}"
The above will result in no output and a returncode of
1while the following will return the vaule and with exit code0:$ jq -n -c 'input | if .condition1 then .condition1 else null | halt_error(1) end' <<<"${my_json_variable}" 42
Outputs without quotes
$ cat output1| jq -r -c '[.[] | .certname,.report_timestamp]'
{host1,2019-10-14T11:26:32.459Z,host2,2019-10-14T11:18:29.598Z}
Outputs full result into one line
$ cat output1| jq -c '[.[] | .certname,.report_timestamp]'
{"host1","2019-10-14T11:26:32.459Z","host2","2019-10-14T11:18:29.598Z"}
Outputs full each result
$ cat output1| jq -c '.[] | {certname:.certname,report_timestamp:.report_timestamp}'
{"certname":"host1","report_timestamp":"2019-10-14T11:26:32.459Z"}
{"certname":"host2","report_timestamp":"2019-10-14T11:18:29.598Z"}
Outputs each result into one line with given vaules
$ cat output1| jq -c '.[] | [.report_timestamp,.certname]'
{"2019-10-14T11:26:32.459Z","host1"}
{"2019-10-14T11:18:29.598Z","host2"}
Sorting by values
$ cat output1| jq -c 'sort_by(.catalog_timestamp,.report_timestamp) | .[] | [.catalog_timestamp,.report_timestamp,.certname]'
{"2019-10-14T11:18:29.598Z","2019-10-14T11:18:29.598Z","host2"}
{"2019-10-14T11:26:32.459Z","2019-10-14T11:26:34.464Z","host1"}
Filter by values
$ cat output1| jq '. | select ( .certname == "host1" )'
{
"certname": "host1",
"report_timestamp": "2019-10-14T11:26:32.459Z"
}
$ cat output1| jq '. | select ( .certname == "host1" ) | .report_timestamp'
"2019-10-14T11:26:32.459Z"
Filter at any values
$ cat output1| jq '. | select ( any(. == "host1") )'
{
"certname": "host1",
"report_timestamp": "2019-10-14T11:26:32.459Z"
}
Filter at any values and contains
$ cat output1| jq '. | select ( any(conatins("ho")) )'
{
"certname": "host1",
"report_timestamp": "2019-10-14T11:26:32.459Z"
},
{
"certname": "host2",
"report_timestamp": "2019-10-14T11:18:29.598Z"
}
Filter at key names using has
$ cat output1 | jq '. | select( has("certname") )
This will return the full hash where it found a key named certname
{
"certname": "host1",
"report_timestamp": "2019-10-14T11:26:32.459Z"
...
},
{
"certname": "host2",
"report_timestamp": "2019-10-14T11:18:29.598Z"
...
}
Filter at keys contain match
$ cat output1 | jq '. | with_entries( select ( .key|contains("name") ))'
{
"certname": "host1"
},
{
"certname": "host2"
}
Filter and remove nested hashes
I had a json output where I needed to find all hosts which have external mountpoints attached + where they got mounted.
To remove the data from a nested hash, without knowing the keys of the hash, you can use something like this:
Json sample:
[{ "hostname": "my_host1", "value": { "/": { "filesystem": "xfs", "size": "10GB", "user": "root", "group": "root" }, "/mnt": { "filesystem": "cifs", "size": "4TB", "user": "mnt_user", "group": "mnt_user" }, "/var": { "filesystem": "xfs", "size": "8GB", "user": "root", "group": "root" } } }, { "hostname": "my_host2", "value": { "/": { "filesystem": "xfs", "size": "12GB", "user": "root", "group": "root" }, "/var": { "filesystem": "xfs", "size": "8GB", "user": "root", "group": "root" }, "/data/shared": { "filesystem": "cifs", "d11": "200GB", "d12": "shared", "d13": "shared" } } }]
$ cat disk_sample.json | jq -r '.[] | select(.hostname | contains("my_")) | select(.. | .filesystem? | select(. == "cifs")) | walk( del( select(.. | .filesystem? | select(. != "cifs") ) ) ) | del(..|select(. == null))'
This will result into:
{
"hostname": "my_host1",
"value": {
"/mnt": {
"filesystem": "cifs",
"size": "4TB",
"user": "mnt_user",
"group": "mnt_user"
}
}
}
{
"hostname": "my_host2",
"value": {
"/data/shared": {
"filesystem": "cifs",
"d11": "200GB",
"d12": "shared",
"d13": "shared"
}
}
}
So what is it doing:
select(.hostname | contains("my_")): ensures that I only get the hosts which contain the stringmy_select(.. | .filesystem? | select(. == "cifs")): It selects all objects which have a child(+childchild…) with thekeyfilesystem and thevaluecifswalk( del( select(.. | .filesystem? | select(. != "cifs") ) ) ): it walks through the result, starting in the deepest level and deletes every objects data containing akeywhich has not thevaluecifs: it walks through the result, starting in the deepest level and deletes every objects data containing thekeyfilesystem which has not the valuecifs.del(..|select(. == null)): Removes all objects where thevalueisnull
To only get now the hostnames + where the storages got mounted, you can add this:
Changed the parameter
-rot-con thejqcommandand appended in the
jqquery this:| walk( del( select(.. | .filesystem? | select(. == "cifs") ) ) )
$ cat test.json| jq -c '.[] | select(.hostname | contains("my_")) | select(.. | .filesystem? | select(. == "cifs")) | walk( del( select(.. | .filesystem? | select(. != "cifs") ) ) ) | del(..|select(. == null)) | walk( del( select(.. | .filesystem? | select(. == "cifs") ) ) ) | [.hostname,.value]'
which leads to this result:
{"hostname":"my_host1","value":{"/mnt":null}}
{"hostname":"my_host2","value":{"/data/shared":null}}
Use Value as Key
Sample json for this and merge sektion section
{
"contacts": [
{
"id": 1,
"name": "Mensch1",
"type": "user"
},
{
"id": 2,
"name": "Team1",
"type": "team"
},
{
"id": 3,
"name": "Mensch2",
"type": "team"
},
{
"id": 4,
"name": "Mensch4",
"type": "user"
},
{
"id": 5,
"name": "Mensch5",
"type": "user"
},
{
"id": 6,
"name": "Team3",
"type": "team"
}
]
}
This is is where the join happens {(.name): .id}, before that we do a sort, to just get all items with type user.
$ jq -r '.contacts | .[] | select (.type == "user") | {(.name): .id}' <./test.json
As resulte we get this:
{
"Mensch1": 1
}
{
"Mensch4": 4
}
{
"Mensch5": 5
}
Merge
To merge the above shown result into one hash, you have to create out of the above result one single array [ ] and pipe it through an add
$ jq -r '[.contacts | .[] | select (.type == "user") | {(.name): .id}] | add' <./test.json
Now you just get one single hash as a result of the add
{
"Mensch1": 1,
"Mensch4": 4,
"Mensch5": 5
}
Variables
External
To use external variables which might contain special characters where which need to me masked or you just want to feed it from the outsoud, you could go this way:
$ jq '{ key: $value }' --arg value 'pas\\\\\3"21T!$!41tsword' -n
{
"key": "pas\\\\\\\\\\3\"21T!$!41tsword"
}