Search code examples
selectconditional-statementsyq

How to select all YAML keys based on a subkey value using yq?


I have a YAML file like this:

$ yq '.' test.yaml
{
  "entries": {
    "entry1": {
      "enabled": true
    },
    "entry2": {
      "enabled": false
    },
    "entry3": {
      "dummy": "TEST"
    }
  }
}

I want to select all entries having enabled attribute set to true:

$ yq '.entries | select(.[].enabled==true)' test.yaml
                         ^  ^
                         |  |
                         |  --- with enabled attribute set to true
                         ------ all entries

I expect the output to be

{
  "entry1": {
    "enabled": true
  }
}

yet I get

{
  "entry1": {
    "enabled": true
  },
  "entry2": {
    "enabled": false
  },
  "entry3": {
    "dummy": "TEST"
  }
}

What did I get wrong?


Solution

  • The trick is to convert the object into an array, apply the selection to the array elements and then convert it back into an object. The filter with_entries does these conversions under the hood. It is a shorthand for to_entries | map(foo) | from_entries (see jq manual).

    The call is slightly different depending on the yq implementation used: yq - Python or yq - Go. The bash script contains calls for both implementations.

    #!/bin/bash
    
    INPUT='
    {
      "entries": {
        "entry1": {
          "enabled": true
        },
        "entry2": {
          "enabled": false
        },
        "entry3": {
          "dummy": "TEST"
        }
      }
    }
    '
    
    echo "yq - Go implementation"       # https://mikefarah.gitbook.io/yq/
    yq -j e '.entries | with_entries(select(.value.enabled == true))' - <<< "$INPUT"
    
    echo "yq - Python implementation"   # https://github.com/kislyuk/yq
    yq '.entries | with_entries(select(.value.enabled == true))' <<< "$INPUT"
    

    output

    {
      "entry1": {
        "enabled": true
      }
    }