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
1
while 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 thekey
filesystem and thevalue
cifswalk( del( select(.. | .filesystem? | select(. != "cifs") ) ) )
: it walks through the result, starting in the deepest level and deletes every objects data containing akey
which has not thevalue
cifs: it walks through the result, starting in the deepest level and deletes every objects data containing thekey
filesystem which has not the valuecifs
.del(..|select(. == null))
: Removes all objects where thevalue
isnull
To only get now the hostnames + where the storages got mounted, you can add this:
Changed the parameter
-r
ot-c
on thejq
commandand appended in the
jq
query 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"
}