title | tags | keywords | last_updated | summary | sidebar | permalink | folder | |
---|---|---|---|---|---|---|---|---|
jq |
|
json, jq |
Jul 14, 2022 |
parse json with jq |
mydoc_sidebar |
misc_jq.html |
Misc |
- jq
- data
- Options
- Types and Values
- Built-in Functions
length
keys
/keys_unsorted
has(key)
map(x)
/map_values(x)
path(path_expression)
del(path_expression)
getpath(PATHS)
setpath(PATHS; VALUE)
to_entries
,from_entries
,with_entries
select(boolean_expression)
arrays
,objects
,iterables
,booleans
,numbers
,normals
,finites
,strings
,nulls
,values
,scalars
paths
add
any
/all
/any(condition)
/all(condition)
range(upto)
/range(from; upto)
/range(from; to; by)
tonumber
/tostring
type
sort
/sort_by(path_expression)
group_by(path_expression)
min
/max
/min_by(path_exp)
/max_by(path_exp)
unique
/unique_by(path_exp)
reverse
contains(element)
indices(s)
index(s)
/rindex(s)
inside(s)
startswith(str)
/endswith(str)
combinations
/combinations(n)
ltrimstr(str)
/rtrimstr(str)
explode
/implode
split(s)
/join(s)
ascii_upcase
/ascii_downcase
while(crondition; update)
/until(crondition; next)
- Examples
=====
$ cat /tmp/data
{
"Subnets": [
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "DEV",
"Key": "Env"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "PrivateSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "PrivateSubnet1a",
"Key": "Name"
}
],
"AvailableIpAddressCount": 214,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-xxxxxx",
"CidrBlock": "10.1.2.0/24",
"AssignIpv6AddressOnCreation": false
},
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "PublicSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "DEV",
"Key": "Env"
}
],
"AvailableIpAddressCount": 250,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-yyyyyy",
"CidrBlock": "10.1.0.0/24",
"AssignIpv6AddressOnCreation": false
}
]
}
$ cat /tmp/jq-data | jq -r -S '.Subnets[0]'
{
"AssignIpv6AddressOnCreation": false,
"AvailabilityZone": "us-east-1a",
"AvailableIpAddressCount": 214,
"CidrBlock": "10.1.2.0/24",
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"MapPublicIpOnLaunch": false,
"State": "available",
"SubnetId": "subnet-xxxxxx",
"Tags": [
{
"Key": "Env",
"Value": "DEV"
},
{
"Key": "aws:cloudformation:stack-name",
"Value": "AccountBase"
},
{
"Key": "aws:cloudformation:logical-id",
"Value": "PrivateSubnet1a"
},
{
"Key": "Owner",
"Value": "Systems"
},
{
"Key": "Name",
"Value": "PrivateSubnet1a"
}
]
}
$ cat /tmp/jq-data | jq -c
{"Subnets":[{"AvailabilityZone":"us-east-1a","Tags":[{"Value":"DEV","Key":"Env"},{"Value":"AccountBase","Key":"aws:cloudformation:stack-name"},{"Value":"PrivateSubnet1a","Key":"aws:cloudformation:logical-id"},{"Value":"Systems","Key":"Owner"},{"Value":"PrivateSubnet1a","Key":"Name"}],"AvailableIpAddressCount":214,"DefaultForAz":false,"Ipv6CidrBlockAssociationSet":[],"State":"available","MapPublicIpOnLaunch":false,"SubnetId":"subnet-xxxxxx","CidrBlock":"10.1.2.0/24","AssignIpv6AddressOnCreation":false},{"AvailabilityZone":"us-east-1a","Tags":[{"Value":"Systems","Key":"Owner"},{"Value":"AccountBase","Key":"aws:cloudformation:stack-name"},{"Value":"PublicSubnet1a","Key":"aws:cloudformation:logical-id"},{"Value":"DEV","Key":"Env"}],"AvailableIpAddressCount":250,"DefaultForAz":false,"Ipv6CidrBlockAssociationSet":[],"State":"available","MapPublicIpOnLaunch":false,"SubnetId":"subnet-yyyyyy","CidrBlock":"10.1.0.0/24","AssignIpv6AddressOnCreation":false}]}
$ cat /tmp/filter
.Subnets[].AvailabilityZone
$ cat /tmp/jq-data | jq -r -f /tmp/filter
us-east-1a
us-east-1a
$ test_cidr='10.1.0.*'
$ jq -r --arg cidr "${test_cidr}" '.Subnets[] | {cidr: .CidrBlock} | select(.cidr | test($cidr))' /tmp/data
{
"cidr": "10.1.0.0/24"
}
parameter as an integer
$ avaiable_ips_threshhold=220
$ jq -r --argjson ip_threshhold "${avaiable_ips_threshhold}" '.Subnets[] | {subnetid: .SubnetId, AvailableIp: .AvailableIpAddressCount} | select(.AvailableIp > $ip_threshhold)' /tmp/data
{
"subnetid": "subnet-yyyyyy",
"AvailableIp": 250
}
$ jq -r --arg ip_threshhold "${avaiable_ips_threshhold}" '.Subnets[] | {subnetid: .SubnetId, AvailableIp: .AvailableIpAddressCount} | select(.AvailableIp > ($ip_threshhold | tonumber))' /tmp/jq-data
{
"subnetid": "subnet-yyyyyy",
"AvailableIp": 250
}
$ cat /tmp/filter | jq .
{
"avaiable_ips_threshhold": 220
}
$ jq -r --slurpfile var /tmp/filter '$var' /tmp/jq-data
[
{
"avaiable_ips_threshhold": 220
}
]
$ jq -r --slurpfile var /tmp/filter '.Subnets[] | {subnetid: .SubnetId, AvailableIp: .AvailableIpAddressCount} | select(.AvailableIp > $var[0].avaiable_ips_threshhold)' /tmp/jq-data
{
"subnetid": "subnet-yyyyyy",
"AvailableIp": 250
}
gets the length of various different types of value
$ cat /tmp/data | jq '.Subnets | length'
2
Count elements based on some specifict conditions
$ jq -r '.Subnets[] | select(.State == "available") | length' /tmp/data
10
10
$ jq -r '[.Subnets[] | select(.State == "available")] | length' /tmp/data
2
returns its keys in an array
$ cat /tmp/data | jq '. | keys[]'
"Subnets"
$ cat /tmp/data | jq '.Subnets[0] | keys_unsorted '
[
"AvailabilityZone",
"Tags",
"AvailableIpAddressCount",
"DefaultForAz",
"Ipv6CidrBlockAssociationSet",
"State",
"MapPublicIpOnLaunch",
"SubnetId",
"CidrBlock",
"AssignIpv6AddressOnCreation"
]
$ cat /tmp/data | jq '.Subnets | keys[]'
0
1
returns whether the input object has the given key / in
returns the input key is in the given object, or the input index corresponds to an element in the given array
$ cat /tmp/data | jq 'has("Subnets")'
true
$ cat /tmp/data | jq '. | keys[] | in({"Subnets": 1})'
true
$ cat /tmp/data | jq '.Subnets | keys[]'
0
1
$ cat /tmp/data | jq '[2] | keys[]'
0
$ cat /tmp/data | jq '.Subnets | keys[] | in([2])'
true
false
# given array '[2]' has only one index: 0
apply filter x
to each element of the input array
$ cat /tmp/data | jq '.Subnets | keys'
[
0,
1
]
$ cat /tmp/data | jq '.Subnets | keys | map(.+1)'
[
1,
2
]
returns array representations of the given path expression in .
. The outputs are arrays of strings (object keys) and/or numbers (array indices).
$ cat /tmp/data | jq '.Subnets[0].SubnetId'
"subnet-xxxxxx"
$ cat /tmp/data | jq 'path(.Subnets[0].SubnetId)'
[
"Subnets",
0,
"SubnetId"
]
removes a key and its corresponding value
$ cat /tmp/data | jq '.Subnets[] | del(.Tags)'
{
"AvailabilityZone": "us-east-1a",
"AvailableIpAddressCount": 214,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-xxxxxx",
"CidrBlock": "10.1.2.0/24",
"AssignIpv6AddressOnCreation": false
}
{
"AvailabilityZone": "us-east-1a",
"AvailableIpAddressCount": 250,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-yyyyyy",
"CidrBlock": "10.1.0.0/24",
"AssignIpv6AddressOnCreation": false
}
returns the values in of each PATHS
.
$ cat /tmp/data| jq 'getpath(["Subnets", 0, "AvailableIpAddressCount"], ["Subnets", 1, "AvailableIpAddressCount"])'
214
250
set VALUE
for PATHS
.
$ cat /tmp/data| jq 'setpath(["Subnets", 0, "AvailableIpAddressCount"]; 0) | .Subnets[].AvailableIpAddressCount'
0
250
to_entries
converts an array to {"key": k, "value": v}
.
from_entries
converts on the opposite way.
with_entries(filter)
is same as to_entries | map(filter) | from_entries
$ cat /tmp/data | jq '.Subnets[].Tags | from_entries'
{
"Env": "DEV",
"aws:cloudformation:stack-name": "AccountBase",
"aws:cloudformation:logical-id": "PrivateSubnet1a",
"Owner": "Systems",
"Name": "PrivateSubnet1a"
}
{
"Owner": "Systems",
"aws:cloudformation:stack-name": "AccountBase",
"aws:cloudformation:logical-id": "PublicSubnet1a",
"Env": "DEV"
}
$ cat /tmp/data | jq '.Subnets[] | to_entries | map(select(.key == "AvailableIpAddressCount"))'
[
{
"key": "AvailableIpAddressCount",
"value": 214
}
]
[
{
"key": "AvailableIpAddressCount",
"value": 250
}
]
$ cat /tmp/data | jq '.Subnets[] | with_entries(select(.key == "AvailableIpAddressCount"))'
{
"AvailableIpAddressCount": 214
}
{
"AvailableIpAddressCount": 250
}
produces its input unchanged if it returns true for that input, and produces no output otherwise.
selects above objects as result
outputs the paths to all the elements, which is similar as path(..)
paths(filter)
output the paths which value match filter
$ cat /tmp/data | jq 'paths(select(.Key? == "Env"))'
[
"Subnets",
0,
"Tags",
0
]
[
"Subnets",
1,
"Tags",
3
]
$ cat /tmp/data | jq 'getpath(["Subnets", 0, "Tags", 0])'
{
"Value": "DEV",
"Key": "Env"
}
$ cat /tmp/data | jq 'getpath(["Subnets", 1, "Tags", 3])'
{
"Value": "DEV",
"Key": "Env"
}
add all elements of input array
$ cat /tmp/data | jq '[.Subnets[].AvailableIpAddressCount] | add'
464
$ cat /tmp/data | jq '[.Subnets[].AvailabilityZone] | add'
"us-east-1aus-east-1a"
$ cat /tmp/data | jq '[.Subnets[] | .AvailabilityZone, .AvailableIpAddressCount | tostring] | add'
"us-east-1a214us-east-1a250"
any
takes an array of boolean values, and returns true
if any of them are true
all
takes an array of boolean values, and returns true
if all of them are true
any(condition)
applies condition
to all elements of given array, and returns true
if any of them are true
all(condition)
applies condition
to all elements of given array, and returns true
if all of them are true
$ cat /tmp/data | jq '[.Subnets[0].AvailableIpAddressCount > 220, .Subnets[1].AvailableIpAddressCount > 220] | any '
true
$ cat /tmp/data | jq '[.Subnets[].AvailableIpAddressCount] | any(. > 220)'
true
$ cat /tmp/data | jq '[.Subnets[].AvailableIpAddressCount] | all(. > 220)'
false
generates a range of numbers from
until upto
with step by
convert input to number or string
returns the type of inputs
sort an array with following order:
null
false
true
- nubmers
- strings (alphabetical order)
- array (lexical order)
- object
or sort the array based onvalue
ofpath_expression
$ jq -r '[.Subnets[].AvailableIpAddressCount]' /tmp/data
[
250,
214
]
$ jq -r '[.Subnets[].AvailableIpAddressCount] | sort' /tmp/data
[
214,
250
]
takes as input an array, groups the elements having the same path_expression
field value into separate arrays, and produces all of these arrays as elements of a larger array.
$ echo '[{"a": 1}, {"b": 2}, {"a": 1}, {"a": 2}]' | jq 'group_by(.a)'
[
[
{
"b": 2
}
],
[
{
"a": 1
},
{
"a": 1
}
],
[
{
"a": 2
}
]
]
get min or max element of input array
$ cat /tmp/data | jq '[.Subnets[].AvailableIpAddressCount] | min '
214
$ cat /tmp/data | jq '[.Subnets[].AvailableIpAddressCount] | max '
250
$ cat /tmp/data | jq '.Subnets | min_by(.AvailableIpAddressCount)'
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "DEV",
"Key": "Env"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "PrivateSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "PrivateSubnet1a",
"Key": "Name"
}
],
"AvailableIpAddressCount": 214,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-xxxxxx",
"CidrBlock": "10.1.2.0/24",
"AssignIpv6AddressOnCreation": false
}
$ cat /tmp/data | jq '.Subnets | max_by(.AvailableIpAddressCount)'
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "PublicSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "DEV",
"Key": "Env"
}
],
"AvailableIpAddressCount": 250,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-yyyyyy",
"CidrBlock": "10.1.0.0/24",
"AssignIpv6AddressOnCreation": false
}
produces an array without duplicated elements from input array.
$ cat /tmp/data | jq '[.Subnets[].Tags[]] | unique'
[
{
"Value": "DEV",
"Key": "Env"
},
{
"Value": "PrivateSubnet1a",
"Key": "Name"
},
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "PrivateSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "PublicSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
}
]
$ cat /tmp/data | jq '[.Subnets[].Tags[]] | unique_by(.Key)'
[
{
"Value": "DEV",
"Key": "Env"
},
{
"Value": "PrivateSubnet1a",
"Key": "Name"
},
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "PublicSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
}
]
reverses an input array
evaluate the element
was included in input
$ cat /tmp/data | jq '.Subnets[].AvailabilityZone | contains("east")'
true
true
$ cat /tmp/data | jq '.Subnets[].Tags[] | contains({"Key": "Env"})'
false
false
false
true
true
false
false
false
false
returns index of s
or value of key s
$ echo '[{"a": 1}, {"b": 2}, {"a": 1}, {"a": 2}]' | jq '.[] | indices("a")'
1
null
1
2
$ echo '[{"a": 1}, {"b": 2}, {"a": 1}, {"a": 2}]' | jq 'indices({"a": 2})'
[
3
]
returns the first index of s
or last index of s
$ echo '[{"a": 1}, {"b": 2}, {"a": 1}, {"a": 2}]' | jq 'index({"a": 1})'
0
$ echo '[{"a": 1}, {"b": 2}, {"a": 1}, {"a": 2}]' | jq 'rindex({"a": 1})'
2
inversed version of contains
$ cat /tmp/data | jq '[.Subnets[0].Tags[] | {key: .Key, value: .Value}] | from_entries[] '
"Systems"
"AccountBase"
"PublicSubnet1a"
"DEV"
$ cat /tmp/data | jq '[.Subnets[0].Tags[] | {key: .Key, value: .Value}] | from_entries[] | startswith("Sys")'
true
false
false
false
$ cat /tmp/data | jq '[.Subnets[0].Tags[] | {key: .Key, value: .Value}] | from_entries[] | endswith("Base")'
false
true
false
false
outputs all combinations of the elements of input arrays. With n
means to output n
repetitions of input array
$ echo '[[1, 2], [3, 4]]' | jq 'combinations'
[
1,
3
]
[
1,
4
]
[
2,
3
]
[
2,
4
]
$ echo '[[1, 2], [3, 4]]' | jq 'combinations(2)'
[
[
1,
2
],
[
1,
2
]
]
[
[
1,
2
],
[
3,
4
]
]
[
[
3,
4
],
[
1,
2
]
]
[
[
3,
4
],
[
3,
4
]
]
trims input string from left or right
convert string to Unicode code point, or convert Unicode code point to string
$ echo '"matrix"' | jq 'explode'
[
109,
97,
116,
114,
105,
120
]
$ echo "[109, 97, 116, 114, 105, 120]" | jq 'implode'
"matrix"
split input based by splitter s
or join all elements with splitter s
$ echo '["matrix"]' | jq '.'
[
"matrix"
]
$ echo '["matrix"]' | jq '.[] | split("")'
[
"m",
"a",
"t",
"r",
"i",
"x"
]
$ echo '["matrix"]' | jq '.[] | split("") | join("")'
"matrix"
convert input to UpperCase or Lowercase
$ echo '["matrix"]' | jq '.[] | ascii_upcase'
"MATRIX"
run update
while contidion
is true
run next
until until condition
is true
$ echo 5 | jq '[., ., 1] | [while(.[1] > 0; [.[0], .[1] - 1, .[2] * .[1]])] | .[length -1][2]'
120
$ echo 5 | jq '[., 1] | until(.[0] < 1; [.[0] - 1, .[1] * .[0]]) | .[1]'
120
$ cat /tmp/data | jq '. | keys[]'
"Subnets"
$ cat /tmp/data | jq '.Subnets | keys[]'
0
1
$ cat /tmp/data | jq '.Subnets[0]'
{
"AvailabilityZone": "us-east-1a",
"Tags": [
{
"Value": "DEV",
"Key": "Env"
},
{
"Value": "AccountBase",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "PrivateSubnet1a",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "Systems",
"Key": "Owner"
},
{
"Value": "PrivateSubnet1a",
"Key": "Name"
}
],
"AvailableIpAddressCount": 214,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-xxxxxx",
"CidrBlock": "10.1.2.0/24",
"AssignIpv6AddressOnCreation": false
}
$ cat /tmp/data | jq '.Subnets[].SubnetId, .Subnets[].CidrBlock'
"subnet-xxxxxx"
"subnet-yyyyyy"
"10.1.2.0/24"
"10.1.0.0/24"
$ cat /tmp/data | jq '.Subnets[] | .SubnetId, .CidrBlock'
"subnet-xxxxxx"
"10.1.2.0/24"
"subnet-yyyyyy"
"10.1.0.0/24"
$ cat /tmp/data | jq '.Subnets[] | .SubnetId, .CidrBlock | select( . == "10.1.0.0/24" )'
"10.1.0.0/24"
$ cat /tmp/data | jq '.Subnets[] | .SubnetId, .CidrBlock | select( . | test(".*1.0.*") )'
"10.1.0.0/24"
$ cat /tmp/data | jq '.Subnets[] | {id: .SubnetId, network: .CidrBlock} | select(.network == "10.1.0.0/24")'
{
"id": "subnet-yyyyyy",
"network": "10.1.0.0/24"
}
$ cat /tmp/data | jq '.Subnets[] | { id: .SubnetId, ip_range: .CidrBlock }'
{
"id": "subnet-xxxxxx",
"ip_range": "10.1.2.0/24"
}
{
"id": "subnet-yyyyyy",
"ip_range": "10.1.0.0/24"
}
$ cat /tmp/ss-instances | jq ' .[][].Instances[] | {id: .InstanceId, tags: .Tags[]} | select(.tags.Key | test("^Name$";"i")) | select(.tags.Value | test(".*netapp.*"))'
jq: error (at <stdin>:34578): Cannot iterate over null (null)
$ cat /tmp/ss-instances | jq ' .[][].Instances[] | {id: .InstanceId, tags: .Tags[]?} | select(.tags.Key | test("^Name$";"i")) | select(.tags.Value | test(".*netapp.*"))'
{
"id": "i-0908ac3819044a7b4",
"tags": {
"Value": "fwawsnetapp01-mediator",
"Key": "Name"
}
}
$ cat /tmp/ss-instances | jq ' .[][].Instances[] | {id: .InstanceId, tags: .Tags[]?} | select(.tags.Key | test("^Name$";"i")) | select(.tags.Value | test(".*netapp.*";"i"))'
{
"id": "i-0b92c0aa4b6758489",
"tags": {
"Value": "System-NetAppCloudManager",
"Key": "Name"
}
}
{
"id": "i-0908ac3819044a7b4",
"tags": {
"Value": "fwawsnetapp01-mediator",
"Key": "Name"
}
}
$ cat /tmp/data
{
"Subnets": [
{
"AvailabilityZone": "us-east-1a",
"SubnetId": "subnet-xxxxxx"
},
{
"SubnetId": "subnet-yyyyyy"
}
]
}
$ jq '.Subnets[] | {az: .AvailabilityZone, subnet: .SubnetId} | select(.az != null).subnet ' /tmp/data
"subnet-xxxxxx"
$ jq -r '.Subnets[] | (.AvailabilityZone + ", " + .CidrBlock)' /tmp/data
us-east-1a, 10.1.2.0/24
us-east-1a, 10.1.0.0/24
$ jq -r '[.Subnets[] | {info: (.AvailabilityZone + ", " + .CidrBlock)}]' /tmp/data
[
{
"info": "us-east-1a, 10.1.2.0/24"
},
{
"info": "us-east-1a, 10.1.0.0/24"
}
]
$ jq -r '.Subnets[] | .AvailabilityZone | split("-")[0]' /tmp/data
us
us
Collects the named captures in a JSON object, with the name of each capture as the key, and the matched string as the corresponding value.
$ jq -r '.Subnets[].AvailabilityZone | capture("(?<country>[^-]+)")' /tmp/data
{
"country": "us"
}
{
"country": "us"
}
{% include links.html %}