24

Bash manual says:

A parameter is set if it has been assigned a value. The null string is a valid value.

...

If value is not given, the variable is assigned the null string.

Is the null string the same as ""?

Are their lengths both zero? Can both be tested by conditional expressions -z or -n which tests if the length of a string is zero or nonzero?

2 Answers 2

26

Yes, a null string in that context is a string of length 0 containing no byte at all. In bash:

var=
var=''
var=""
var=$''
var=$""
var=$(true) # or any command that outputs nothing or only newline
            # characters
var=`true`
var=${null_or_unset_var}
var=''""$''$""$(true)"`true`"

But also in bash, as a side effect of bash (contrary to zsh) not supporting NUL bytes in its variables (as it uses NUL-delimited C strings internally):

var=$'\0'
var=$'\u0000'
var=$'\c@'
var=$'\x00'
var=$'\0\0\0\0\0'

In all those cases, $var will be set but contain nothing (the null string). echo "${#var}" will output 0, [ -z "$var" ] will return true and printf %s "$var" will output nothing.

After unset var (but beware of the bug/misfeature of bash, mksh and yash where unset may reveal a version of $var from an outer scope instead of unsetting it if you're doing that from a function called from another function that had declared the variable local), $var has no value, null or not.

However $var still expands to nothing (to the null string) unless the nounset option is on. There are other differences between unset variables and variables assigned an empty value:

  • ${var?} triggers an error when $var is unset
  • ${var+x} expands to x if $var has any value (even null)
  • ${var-x} expands to x if $var is unset
  • [[ -v var ]] returns false if $var is unset
  • if the variable is marked for export, then var= is passed in the environment of every command if it's set, or not passed at all otherwise.
3
  • Would it be correct to say a shell does not have zero-length strings and setting a string to "" value will make it a null string? Also you say "$var still expands to nothing (to the null string)", but so does any non-declared variable. Do you see any difference between unset variable and variable never declared? Unset also removes variable type and "export" state. It seems more like "undeclare". Except that it behaves differently with "local" variables, which is not consistent as you too mentioned.
    – papo
    Oct 25, 2020 at 15:35
  • ${parameter:+word} Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted. If I understand correctly, the docs are wrong here? Since for a null (empty) parameter, it does return the expanded word! Jan 12, 2023 at 0:01
  • Looks like I missed this important paragraph just before: When not performing substring expansion, using the forms documented below (e.g., :-), bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset. Jan 18, 2023 at 0:46
14

Yes. Using the test from this answer:

$ [ -n "${a+1}" ] && echo "defined" || echo "not defined"
not defined
$ a=""
$ [ -n "${a+1}" ] && echo "defined" || echo "not defined"
defined
$ b=
$ [ -n "${b+1}" ] && echo "defined" || echo "not defined"
defined

So setting the variable to "" is the same as setting it to empty value. Therefore, empty value and "" are the same.

3
  • I think it would be better to have a reference to the documentation, rather than a set of extensional tests to support this claim.
    – kirelagin
    Aug 6, 2020 at 15:48
  • @kirelagin, I agree, but Bash manual does not define a term "null string". The closest it gets is in section 3.5.7, "Word splitting", where "" and '' are called "explicit nulls". Aug 7, 2020 at 16:11
  • 1
    It’s quite sad, but it looks like you are right indeed. I am a little surprised that shell documentation can be that ambiguous.
    – kirelagin
    Aug 24, 2020 at 19:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .