T-One T-One - 1 month ago 13
Bash Question

If Variable 1 is defined, variable 2 must be empty and vice versa in bash

I have a bit of a problem with a getopts construct.
I define multiple variables via getopts and have some conditions I have to check before going further in the script.

The user shouldn't be able to define two special options together (

-t
for
$target
and
-tg
for
$targetgroup
). So what I'm looking for is a construct that checks:


  • if
    $target
    is defined, then
    $targetgroup
    must be empty, and

  • if
    $targetgroup
    is defined
    $target
    must be empty.



I've done a workaround with
[[ -z $target ]]
,
[[ -n $targetgroup ]]
and checking the exit codes, but I think this approach is just simply wrong.

Is there any easy way to accomplish this?

Answer

For testing a 1-of-n condition like this, we can use parameter expansion with the :+ modifier. ${target:+1} expands to 1 only when $target is non-empty. So you can test that "${target:+1}${targetgroup:+1}" doesn't contain more than one 1:

if [[ ${target:+1}${targetgroup:+1} == 11* ]]
then
    echo 'Error: it is invalid to specify both -t and -tg' >&2
    exit 1
fi

For this particular case (where there are only two mutually-exclusive variables), we don't need the * in the pattern. It's there so that you can easily add more options that must not be used together with either of these two, without needing to change anything else.

You could also use it where you're allowed up to any n of a set of arguments; to do so, you would write n+1 1s in the match string.

If you want exactly one of the two options to be supplied, then change the test to != 1.