I forgot the closing parenthesis:
aws ecs list-services --cluster splat-dev --profile mfa |
jq -r '.serviceArns[] | select(contains("edp-api-dev"))'
# ^
Answer from kumar on Stack Overflowshell - Get an array containing partially matching search word from a json array with jq - Unix & Linux Stack Exchange
JQ - filter datasets in array based on index value within each dataset of array.
json - jq: how to filter an array of objects based on values in an inner array? - Stack Overflow
How do I filter the contents of a json array, but keep the parent with jq? - Unix & Linux Stack Exchange
Other answers have suggested using ? which is very good. Another way is to use the built-in objects filter which discards an input if it is not an object:
map(objects | select(.b == 2))
# ^^^^^^^ ^^^^^^^^^^^^^^^
# A B
A: filter out non-objects
B: At this point, we're dealing with objects
Slightly more verbose and perhaps less efficient?
There are a few options.
Ignore errors using ?:
map(select(.b? == 2))
docs, jqplay
Check the value's type in your select filter:
map(select(type == "object" and .b == 2))
docs, jqplay
Filter out non-objects:
map(objects | select(.b == 2))
docs, jqplay
A slightly different approach from what rowboat took:
jq 'map(select(any(contains("a"))))' file
The innermost test tests each of the strings for the substring a. If any string in a sub-array contains a, that sub-array is selected. The map applies the selection to all sub-arrays in the top-level array.
The result is a top-level array with sub-arrays that contain at least one element that contains the substring a:
[
[
"a",
"b",
"c"
],
[
"abc",
"e",
"f"
]
]
jq '[.[] | select(contains(["a"]))]'
With your input array:
$ jq -c << \\ '[.[] | select(contains(["a"]))]'
[
["a", "b", "c"],
["abc", "e", "f"],
["g", "h", "i"]
]
\
[["a","b","c"],["abc","e","f"]]
man jq (https://stedolan.github.io/jq/manual/) is a bit long, but I think the relevant part is:
The filter
contains(b)will produce true if b is completely contained within the input. A string B is contained in a string A if B is a substring of A. An array B is contained in an array A if all elements in B are contained in any element in A.jq 'contains(["baz", "bar"])' Input ["foobar", "foobaz", "blarp"] Output true
Very close! In your select expression, you have to use a pipe (|) before contains.
This filter produces the expected output.
. - map(select(.Names[] | contains ("data"))) | .[] .Id
The jq Cookbook has an example of the syntax.
Filter objects based on the contents of a key
E.g., I only want objects whose genre key contains "house".
$ json='[{"genre":"deep house"}, {"genre": "progressive house"}, {"genre": "dubstep"}]' $ echo "$json" | jq -c '.[] | select(.genre | contains("house"))' {"genre":"deep house"} {"genre":"progressive house"}
Colin D asks how to preserve the JSON structure of the array, so that the final output is a single JSON array rather than a stream of JSON objects.
The simplest way is to wrap the whole expression in an array constructor:
$ echo "$json" | jq -c '[ .[] | select( .genre | contains("house")) ]'
[{"genre":"deep house"},{"genre":"progressive house"}]
You can also use the map function:
$ echo "$json" | jq -c 'map(select(.genre | contains("house")))'
[{"genre":"deep house"},{"genre":"progressive house"}]
map unpacks the input array, applies the filter to every element, and creates a new array. In other words, map(f) is equivalent to [.[]|f].
Here is another solution which uses any/2
map(select(any(.Names[]; contains("data"))|not)|.Id)[]
with the sample data and the -r option it produces:
cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b
a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19
If "rebuilding" your structure is an option you could do something like this
jq '.Vpcs[]|select(.OwnerId!="abc")|{Vpcs: [.]}'
You could also use del() as:
jq 'del(.Vpcs[]|select(.OwnerId == "abc"))'
Or:
jq 'del(..|select(.OwnerId? == "abc"))'
To delete objects that have a OwnerId attribute set to "abc" wherever they are in the JSON data.
Note that would change {"key":{"OwnerId":"abcd"}} to {}. The "key" is also lost there.
From the docs:
jq '.[] | select(.id == "second")'Input
[{"id": "first", "val": 1}, {"id": "second", "val": 2}]Output
{"id": "second", "val": 2}
I think you can do something like this:
jq '.theList[] | select(.id == 2 or .id == 4)' array.json
You could use select within map.
.theList | map(select(.id == (2, 4)))
Or more compact:
[ .theList[] | select(.id == (2, 4)) ]
Though written that way is a little inefficient since the expression is duplicated for every value being compared. It'll be more efficient and possibly more readable written this way:
[ .theList[] | select(any(2, 4; . == .id)) ]