Home > Mobile >  Bash: ensuring a variable is set without erasing any existing value
Bash: ensuring a variable is set without erasing any existing value

Time:09-12

Let's say I'm running a bash script under set -u. Obviously, for any given variable, I need to ensure that it's set. Something like:

foo=

However, if I want to keep any pre-existing value that might be set by my caller, this would overwrite it. A simple solution to this problem is to do this instead:

: ${foo:=}

But I have some code that does this (more complicated) way:

foo=${foo $foo}

Now, I know this second way works. My question is, is there any advantage to it over the first way? I am assuming there is but now can't remember what it was. Can anyone either think of an edge case (no matter how obscure) where these two constructs would behave differently, or provide a compelling explanation that they can't?

CodePudding user response:

I can't think of any case where they would differ. They're just alternative logic for the same thing.

The meaning of the simple solution is: If foo is unset/empty, set it to the empty string.

The meaning of your code is: If foo is set, set it to itself, otherwise set it to an empty string.

Your code seems like more work -- why set something to itself? Just do nothing and it will keep its value. That's what the simpler version does.

You can also simplify the simple solution further by removing the : in the parameter expansion.

: ${foo=}

This makes it only test whether foo is unset. If it's set to the empty string, no default needs to be assigned.

CodePudding user response:

My question is, is there any advantage to it over the first way?

Maybe this is subjective, but one advantage is that it clearly looks like a variable assignment. Anyone who sees the command foo=${foo $foo} will immediately understand that it sets the variable foo (even if they need to look up the ${parameter word} notation to figure out what it sets it to); but someone who sees the command : ${foo:=} is likely to completely miss that it has the side-effect of modifying foo. (The use of : is definitely a hint that something might be happening, since : itself does nothing; but it's not as blatant.)

And of course, someone searching the script for foo= will find the former but not the latter.

That said, I would personally write this as either foo="${foo-}" or foo="${foo:-}", which still makes clear that it sets foo, but is a bit simpler than foo=${foo $foo}. I also think that readers are more likely to be familiar with ${parameter-word} than ${parameter word}, but I haven't asked around to check.

  •  Tags:  
  • bash
  • Related