Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Conditionals and Comparisons 'if-then-else' #95

Open
kenjones-cisco opened this issue Sep 27, 2017 · 10 comments
Open

Add support for Conditionals and Comparisons 'if-then-else' #95

kenjones-cisco opened this issue Sep 27, 2017 · 10 comments

Comments

@kenjones-cisco
Copy link
Contributor

Add support for Conditionals and Comparisons 'if-then-else'

if A then B else C end will act the same as B if A produces a value other than false or null, but act the same as C otherwise.

Checking for false or null is a simpler notion of “truthiness” than is found in Javascript or Python, but it means that you’ll sometimes have to be more explicit about the condition you want: you can’t test whether, e.g. a string is empty using if .name then A else B end, you’ll need something more like if (.name | length) > 0 then A else B end instead.

If the condition A produces multiple results, then B is evaluated once for each result that is not false or null, and C is evaluated once for each false or null.

More cases can be added to an if using elif A then B syntax.
@rLitto
Copy link

rLitto commented Aug 6, 2021

Has it been implemented?

@CyberShadow
Copy link

Has it been implemented?

No:

yq e --null-input 'if true then 2 else 3 end'
Error: Parsing expression: Lexer error: could not match text starting at 1:1 failing at 1:3.
	unmatched text: "if"

@mikefarah I think you closed this by accident.

@76creates
Copy link

really odd that we don't have conditionals, i see all related issues are closed without any comments
#94
#96
#97

@mikefarah can you please comment on these? is it going to be implemented, if not can we get any rationale?

@mikefarah
Copy link
Owner

Oops - sorry I closed a bunch of issues back then that didn't seem to have anyone interested in them (then didn't see the comments). Re opening.

@mikefarah mikefarah reopened this Mar 15, 2022
@sorvis
Copy link

sorvis commented Sep 23, 2022

There is a work around detailed here in the docs:

https://mikefarah.gitbook.io/yq/usage/tips-and-tricks#logic-without-if-elif-else

@sarimarton
Copy link

There is a work around detailed here in the docs:

https://mikefarah.gitbook.io/yq/usage/tips-and-tricks#logic-without-if-elif-else

How can I use it as an expression in a .map?

@planeiii-te
Copy link

It sure would be nice to have more than one demo. Maybe something more complex perhaps.

@robross0606
Copy link

robross0606 commented Jul 1, 2024

The workaround does leave a lot to be desired. For example, I have been unable to figure out how to adapt that example to changing a single YAML string based on the value of an environment variable. Or any other (seemingly simpler) conditional related to a single string. Or to straight-up omit() a key if another value is set to a specific known value.

As far as I can tell, the second you select() something, it is no longer available to re-iterate for the "else" scenario. The only reason the workaround works in the example is because it is iterating once per value in the map. But what if you need to have an "else" for a single value?

I've tried using eval() with select() but haven't been able to get that to work either.

@robross0606
Copy link

robross0606 commented Jul 1, 2024

Probably the biggest thing not clearly documented is, what happens with select() when nothing matches? For example, I've tried this:

 myvar=foo yq -n 'select(strenv(myvar) == "fred") | "hello"'

This prints "hello". But why if myvar clearly doesn't equal "fred"?

@git-developer
Copy link

git-developer commented Oct 13, 2024

Looks like the result of the select step (some kind of "missing context") is given to the "hello" step; the literal "hello" doesn't depend on this context, so it is not skipped but evaluated.

This workaround references the context . so that the "if-case" is skipped on missing context:

$ myvar=fred yq -n '(select(strenv(myvar) == "fred") | . = "is-fred") // "is-not-fred"'
is-fred

$ myvar=foo yq -n '(select(strenv(myvar) == "fred") | . = "is-fred") // "is-not-fred"'
is-not-fred

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

11 participants