5

I see a lot of shell scripts (for example, this one) checking for a variable's presence/absence like:

[ -n "${VAR-}" ]

As far as I can tell, using the ${VAR-fallback} form without providing a fallback serves no purpose when checking for variable presence/absence (-n or -z). The same goes for ${VAR:-fallback}. For example, with an unset variable,

unset VAR
[ -z "$VAR" ]       &&
  [ -z "${VAR-}" ]  &&
  [ -z "${VAR:-}" ] &&
  echo True        # => True

and with a null variable

VAR=
[ -z "$VAR" ]       &&
  [ -z "${VAR-}" ]  &&
  [ -z "${VAR:-}" ] &&
  echo True        # => True

But I see it in enough places that I have to ask, am I missing something? Is it just a misunderstanding that results in misuse, or is there actually a reason to do it?

2 Answers 2

7

If set -u is in effect, and VAR is unset, [ -z "$VAR" ] will cause an error. With [ -z "${VAR-}" ] the default value overrides the check for using an unset variable, and there is no error.

13
  • Well, set -u is very unusual in practice, and normally would only be seen inside the script itself, which again would be highly unusual. It can be useful for debugging I suppose, but defending against it in normal scripting is pedantic, to say the least. Commented Jun 15, 2017 at 4:23
  • BTW, use of set -u in conjunction with pervasive use of ${VAR:-} would be self-defeating to the extreme. Commented Jun 15, 2017 at 4:27
  • @GregA.Woods, regardless of how usual it is, if it's enabled, there is a difference. I do rather find set -u useful. Not as a way to crash on purpose, but as a way to hedge against mistyping variable names. Even if you used "${foo-}" everywhere, it would have the advantage of explicitly making you think about the possibility of the variable being unset. Commented Jun 15, 2017 at 4:28
  • 1
    ${var-} is useful when checking if a variable that comes from outside the script itself is set or empty (or ${var+x} to check if it's set). I've used stuff like set -u; if [ -z "${1-}" ] ; then complain... (Yes, you could use $# for positional parameters, but not for some environment variable in general.) Commented Jun 15, 2017 at 12:51
  • 2
    I also find it a lot more robust to avoid relying on any distinction between empty and unset variables, especially in shell scripts. Binary logic is usually much easier to follow and prove correct than ternary logic. Commented Jun 15, 2017 at 17:18
-2

You are absolutely right -- there is no reason to use the form ${VAR:-} nor the form ${VAR-} with either test -n or test -z.

I've not seen this myself, so I can only guess that inexperienced shell programmers might think there's some difference between an unset value and an empty value with respect to how test -n works, but that could only happen if test (i.e. [) is both a built-in, and buggy; or if someone is trying to use set -u without thinking through the implications of then defending against it in this manner.

6
  • Is ${VAR-} really deprecated? It's behavior differs from the :- version if VAR is set to null. Commented Jun 15, 2017 at 4:10
  • 2
    ${VAR:-foo} and ${VAR-foo} are not the same, and there's no reason to think one is deprecated. (Okay, fine, with an empty default value, there's no difference.) Commented Jun 15, 2017 at 4:11
  • Well, there's been no mention of ${VAR-} in POSIX since at least 1003.1-2004. It's not in the 10th Edition Research Unix manual either, and that came out in 1989. Commented Jun 15, 2017 at 4:17
  • 2
    @GregA.Woods, IEEE Std 1003.1-2008, 2016 Edition, Shell Command Language/Parameter Expansion. There's a nice table of the eight similar forms. The manuals for some shells are a bit more vague on it, e.g. Bash's manual only mentions in the middle of the text what happens if the colon is omitted. Commented Jun 15, 2017 at 4:37
  • Ah, my mistake -- my reference to the 2004 edition was incomplete. (I wish POSIX hadn't used the word "null" to refer to an empty shell variable. To most programmers with experience with pointers (or SQL for that matter) "null" means un-set, and "empty" is, well, empty.) Commented Jun 15, 2017 at 5:10

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.