jq - How to filter a json that does not contain

JsonJq

Json Problem Overview


I have an aws query that I want to filter in jq. I want to filter all the imageTags that don't end with "latest"

So far I did this but it filters things containing "latest" while I want to filter things not containing "latest" (or not ending with "latest")

aws ecr describe-images --repository-name <repo> --output json | jq '.[]' | jq '.[]' | jq "select ((.imagePushedAt < 14893094695) and (.imageTags[] | contains(\"latest\")))"

Thanks

Json Solutions


Solution 1 - Json

You can use not to reverse the logic

(.imageTags[] | contains(\"latest\") | not)

Also, I'd imagine you can simplify your pipeline into a single jq call.

Solution 2 - Json

In this case contains() doesn't work properly, is better use the not of index() function

select(.imageTags | index("latest") | not)

Solution 3 - Json

All you have to do is | not within your jq

A useful example, in particular for mac brew users:

List all bottled formulae

by querying the JSON and parsing the output

brew info --json=v1 --installed | jq -r "map(select(.installed[].poured_from_bottle) | .name) | unique | .[]" | tr '\n' ' '
List all non-bottled formulae

by querying the JSON and parsing the output and using | not

brew info --json=v1 --installed | jq -r "map(select(.installed[].poured_from_bottle | not) | .name) | unique | .[]"

Solution 4 - Json

This .[] | .[] can be shorten to .[][] e.g.,

$ jq --null-input '[[1,2],[3,4]] | .[] | .[]'
1
2
3
4
$ jq --null-input '[[1,2],[3,4]] | .[][]'
1
2
3
4

To check whether a string does not contain another string, you can combine contains and not e.g.,

$ jq --null-input '"foobar" | contains("foo") | not'
false
$ jq --null-input '"barbaz" | contains("foo") | not'
true

You can do something similar with an array of strings with either any or all e.g.,

$ jq --null-input '["foobar","barbaz"] | any(.[]; contains("foo"))'
true
$ jq --null-input '["foobar","barbaz"] | any(.[]; contains("qux"))'
false
$ jq --null-input '["foobar","barbaz"] | all(.[]; contains("ba"))'
true
$ jq --null-input '["foobar","barbaz"] | all(.[]; contains("qux"))'
false

Say you had file.json:

[ [["foo", "foo"],["foo", "bat"]]
, [["foo", "bar"],["foo", "bat"]]
, [["foo", "baz"],["foo", "bat"]]
]

And you only want to keep the nested arrays that don't have any strings with "ba":

$ jq --compact-output '.[][] | select(all(.[]; contains("bat") | not))' file.json
["foo","foo"]
["foo","bar"]
["foo","baz"]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGavriel FishelView Question on Stackoverflow
Solution 1 - JsonJ. DoeView Answer on Stackoverflow
Solution 2 - JsonJose Ernesto SuarezView Answer on Stackoverflow
Solution 3 - JsonjasonleonhardView Answer on Stackoverflow
Solution 4 - JsoncustomcommanderView Answer on Stackoverflow