Is it possible to do a inverse match using yq

50 Views Asked by At

i wanted to do inverse match of a yml as below

Input yml content :

....
....

validate-common-non-production:
  stage: validate-common-non-production

deploy-common-non-production:
  stage: deploy-common-non-production

validate-common-production:
  stage: validate-common-production

deploy-common-production:
  stage: deploy-common-production

...
...

expected output :

....
....

validate-common-non-production:
  stage: validate-common-non-production

deploy-common-non-production:
  stage: deploy-common-non-production
...
...

can this be archived using yq, i want to remove all the objects ending with production but excluding the ones having non-production. also using regex rather than using full key name to select

1

There are 1 best solutions below

0
pmf On

As you've used the tag, please follow its requirements and specify which implementation of yq you are targeting: kislyuk/yq written in Python or mikefarah/yq written in Go. Ideally, also indicate the version used.

all the objects ending with production but excluding the ones having non-production

Also, it's not clear from the question whether you want to test against the top-level object's keys or the values of the child object's .stage key.

I'm going to address some of the possible combinations. Please clarify if your intended one is missing.

With kislyuk/yq, you can use endswith and not to make negative ascertainments. Access the top-level .key using with_entries.

yq -y 'with_entries(select(.key | endswith("non-production") or (endswith("production") | not)))'

Or, if you want to use regular expressions, use test with $ to find final matches, and compile a negative lookbehind using ?<!.

yq -y 'with_entries(select(.key | test("(?<!non-)production$") | not))'

To use the .stage value instead, replace .key with .value.stage inside with_entries.

As for mikefarah/yq, it unfortunately doesn't implement endswith. And while regular expressions are implemented, negative lookbehinds don't seem to be supported. But you can use globbing with * instead.

yq 'del(.[] | select(key == "*production" and key != "*non-production"))'

To use the .stage value instead, replace key with just .stage.

Given your (rectified) sample input, all of these output:

validate-common-non-production:
  stage: validate-common-non-production
deploy-common-non-production:
  stage: deploy-common-non-production

Tested with kislyuk/yq v3.2.3 and mikefarah/yq v4.35.1