如何过滤不包含特定内容的json数据(使用jq命令)

77

我有一个 AWS 查询,想要在 jq 中进行筛选。我想过滤掉所有以 "latest" 结尾的 imageTags

目前我做了这个,但它会筛选包含 "latest" 的内容,而我想筛选不包含 "latest"(或不以 "latest" 结尾)的内容。

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

谢谢


请提供一个最小化、完整可验证的示例(参见http://stackoverflow.com/help/mcve)。其中一个原因是您的问题描述不清楚是否需要使用“any”(或等效物)。 - peak
可能是重复的问题,参考如何使用jq根据内部数组中的值过滤对象数组? - Gavriel Fishel
4个回答

122

你可以使用not来反转逻辑。

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

此外,我想你可以将你的流程简化为一个单独的jq调用。


嘿,感谢您的回答, 我尝试运行它,但是出现了以下错误:aws ecr describe-images --repository-name embed-service --output json | jq '.[]' | jq '.[]' | jq "select (.imageTags[] | contains("latest") | not)"jq: error: Cannot iterate over null但是我确实有没有“latest”的imageTags。 - Gavriel Fishel
多么奇怪。你能否给出一个你正在处理的JSON示例? - J. Doe
1
我之前没有想到的思维差距在于contains()是一个终端过滤器,只返回truefalse。要反转它,只需将其管道传递给not!事后看来这是如此明显... - mgalgs
@GavrielFishel:这条消息意味着一些图像没有标签。试试这个修复方法:"aws ecr describe-images --repository-name embed-service --output json | jq '.[]?' | jq '.[]?' | jq "select (.imageTags[]? | contains("latest") | not)" - user3630264
1
请注意,如果您正在进行多个评估,则必须将其放在相同的反转管道中。.stuff[] | contains("thing") | not,而不是 (.stuff[] | contains("thing")) | not - Chaim Eliyah

6

你只需要在 jq 中使用 | not 即可

这是一个特别适用于 Mac brew 用户的实用示例:

列出所有瓶装配方

通过查询 JSON 并解析输出来实现

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

列出所有非瓶装配方

通过查询JSON并解析输出,使用| not

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

5

这个 .[] | .[] 可以缩写为 .[][] 例如,

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

要检查一个字符串是否不包含另一个字符串,可以将containsnot组合使用,例如:

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

你可以使用字符串数组和 anyall 来实现类似的功能,例如:
$ 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

假设你有一个 file.json 文件:

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

您只想保留没有包含"ba"字符串的嵌套数组:

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

all()和any()对我很有帮助!谢谢! - Tim

5
在这种情况下,contains() 函数不能正常工作,最好使用 index() 函数的 not 来代替。
select(.imageTags | index("latest") | not)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接