Home > Back-end >  jq combine positive and negative filters with select
jq combine positive and negative filters with select

Time:03-08

Given the following JSON object "test.json":

{
    "results": [
        {"name": "package-dev_0.0.1-dev.er56ut.pkg"},
        {"name": "package-dev_0.0.23-master.qwk89mo.pkg"},
        {"name": "package_0.9.1-dev.til39aw.pkg"},
        {"name": "package_0.3.3-master.mbw80lk.pkg"}
    
    ]
}

I am trying to use jq to filter for instances where the key "name" contains "dev" but does not contain "master" and output the value of "name".

Filtering for instances where the key "name" contains "dev" is fine:

cat test.json | jq '.results[]|select(.name|contains("dev")) | .name'
"package-dev_0.0.1-dev.er56ut.pkg"
"package-dev_0.0.23-master.qwk89mo.pkg"
"package_0.9.1-dev.til39aw.pkg"

But I haven't been successful in removing instances where the key "name" contains "master":

cat test.json | jq '.results[]|select(.name|contains("dev")) | select(.name|contains("master"))|not'
false

CodePudding user response:

Use not, which is a builtin rather than an operator:

.results[] | select(.name | contains("dev") and (contains("master") | not)) | .name
"package-dev_0.0.1-dev.er56ut.pkg"
"package_0.9.1-dev.til39aw.pkg"

Demo

Alternatively, you can collect your tests in an array and test against that

.results[] | select([.name | contains("dev", "master")] == [true, false]) | .name
"package-dev_0.0.1-dev.er56ut.pkg"
"package_0.9.1-dev.til39aw.pkg"

Demo

  • Related