I'm limited to Bash.
I want to echo one of two strings, depending on whever a parameter is set, or not.
Let's say
if $ARG is notset|empty then print X
if $ARG is set&nonempty then print V
I'm totally not interested in $ARG contents. Just if it is provided&filled or not.
I know I can get this outcome by IF/CASE/etc. But I'll use this construct quite a few times, and I want to keep it concise. I know I can do it in whatever way and wrap it into a function, but I'm curious if it can be made in some smart way i.e. with parameter expansion?
I've read through https://tldp.org/LDP/abs/html/parameter-substitution.html and a few similar pages, and I noticed that there are two similar, seemingly complementary operations:
default value: ${ARG:-X}
alternative value: ${ARG:+V}
This is where the question title comes from by the way. :-
returns X when empty, :+
returns V when nonempty.
A simple:
echo ${ARG:+V}${ARG:-X}
does almost what I want. Prints out X
when $ARG
is empty or not set, but in any other case, say ARG=foo, it prints out Vfoo
. That's because :+
and :-
aren't really complementary in the way I want ;) To get it working with simple concatenation like ${}${}
I'd need an 'inverse' :+
that outputs 'default' when empty, or outputs nothing (not: the tested variable).
Seems I'd need some monster compund command like ${ARG:+V:-X}
(which doesn't work, since it's :+
with V:-X
as the alt_value), that does this in a one go, chooses between two given values according to the state of the parameter, and doesn't really use the actual text that parameter holds.
I naively tried nesting
echo ${${ARG:+V}:-X}
which would do exactly what I needed, and it didn't work in Bash, since it's parameter expansion, and the inner ${ARG:+V}
isn't a parameter, so the outer ${}
complains. (~ Can command substitution be nested in variable substitution?)
I thought I could try fixing up Vfoo
by cutting it down to first character ${xxx:0:1}
, but then, this would require nesting again ${${ARG:+V}${ARG:-X}:0:1}
, so no-go.
Or a helper variable, and in this case it's fine:
MINGW64 ~
$ f () { T=${1:+V}${1:-X} ; echo ${T:0:1} ; } ;
$ f "a"
V
$ f ""
X
$ f
X
This is as close as I could get, and even has the behavior I wanted.
Feels a bit dirty, since it actually constructs arbitrarily-long string T
just to get its first char. Pure waste.
Also I still would like to squash it into a single expression, without a temporary variable T
.
Did I miss something in Bash? Can I somehow get this 'choice' behavior in a better way with parameter expansions, or any other built-in tricks?
if [[ -z "$ARG" ]]; then echo X; else echo Y; fi
?$(X:-Y)
that are relatively easy to type, less chars, less typos, especially when typed ad-hoc on commandline. And since there already are :- and :+, which are so close, it feels like I overlooked somethingf
, this isn't all that worse. It could be shortened to something like[ -z "ARG" ] && echo X || echo Y