arraysfiltercontainsyq

YQ - how to filter an array by field value if matching at least one element in a list


Specifically (https://github.com/mikefarah/yq) 4.35+

I have a comma-separated string of terms and I want to filter down a list if a field value is one of those terms.

Ex) Given the following input:

- name: bob
  age: 12
- name: jen
  age: 22
- name: mork
  age: 4003

Include elements whose name field value exists as a substring of "jen,mork" such that the output is:

- name: jen
  age: 22
- name: mork
  age: 4003

I can also represent the terms as a string array, i.e. ["jen", "mork"]

So the equivalent of something like:

yq 'filter("jen,mork" | contains(.name))' array.yaml
# Though I'm not sure how `contains` gets the original array context
# or
yq 'filter(.name in ["jen", "mork"])' array.yaml

I realize this can be done by building an or set, as follows:

yq 'filter(.name == "jen" or .name == "mork"])' array.yaml

but I was hoping for something a little more elegant.

I'm not really sure what to try as it seems this is backwards to how the operators want to work.


Solution

  • Simply construct a stream, and the comparison will automatically iterate over its items:

    yq 'filter(.name == ("jen", "mork"))' array.yaml
    

    To import the list, use an environment variable, and env to access it:

    list='["jen", "mork"]' yq 'filter(.name == (env(list) | .[]))' array.yaml
    

    With yq v4.44.2, you can shorten to .name == env(list)[].

    Output:

    - name: jen
      age: 22
    - name: mork
      age: 4003