Search code examples
yamlyq

How to return a pruned yaml tree with only the top few levels in yq


I'd like to return a simplified, filtered yaml document based on some nested keys. I haven't yet found how to accomplish this, but given how powerful mikefarah/yq is, I'm confident it is doable.

Given input:

ns-a:
  name-a:
  -
    prop-a: "aye"
    prob-b:
      stuff: "that doesn't matter"
    target-prop: "just-me"
  -
    prop-a: "aye"
    target-prop: "not-me"
  name-b:
  -
    prop-a: "aye"
    target-prop: "just-me"
  -
    prop-a: "aye"
    prob-b:
      stuff: "that doesn't matter"
    target-prop: "not-me"
ns-b:
  name-a:
  -
    prop-a: "aye"
    target-prop: "just-me"
  -
    prop-a: "aye"
    prob-b:
      stuff: "that doesn't matter"
    target-prop: "not-me"
  name-b:
  -
    prop-a: "aye"
    target-prop: "just-me"
  -
    prop-a: "aye"
    prob-b:
      stuff: "that doesn't matter"
    target-prop: "not-me"

I would like to return:

ns-a:
  name-a:
  -
    target-prop: "just-me"
  name-b:
  -
    target-prop: "just-me"
ns-b:
  name-a:
  -
    target-prop: "just-me"
  name-b:
  -
    target-prop: "just-me"

Where the structure remains intact, but only the target-prop is exposed and only when it is "just-me".

I can sort of accomplish this with ripgrep, but this is not the ideal way to deal with structured data.

rg -N '^\w|^  \w|target-prop: "just-me"' tmp.yaml

Yields:

ns-a:
  name-a:
    target-prop: "just-me"
  name-b:
    target-prop: "just-me"
ns-b:
  name-a:
    target-prop: "just-me"
  name-b:
    target-prop: "just-me"

Close, but no cigar.


Solution

  • You could update |= at the second level .[][] by reducing the array items to objects only containing the desired key using pick, then select those that match in content, and take the first using .[0] (structurally, there could be more than just one, as in your sample):

    yq '.[][] |= (map(pick(["target-prop"]) | select(.[] == "just-me")) | .[0])'
    
    ns-a:
      name-a:
        target-prop: "just-me"
      name-b:
        target-prop: "just-me"
    ns-b:
      name-a:
        target-prop: "just-me"
      name-b:
        target-prop: "just-me"
    

    Tested with mikefarah/yq v4.34.2