2014-11-19 17:35:30 -0600, Eduardo A. Bustamante López: > > So far, so good. But.... > > > > imadev:~$ foo() { echo foo; } > > imadev:~$ foo=bar > > imadev:~$ is_defined3 foo ; echo $? > > 1 > > Ouch! Last try: > > is_defined4() { > declare -p -- "$1" 2>/dev/null >&2 > } > > But I agree with you, the shell is tricky.
Bearing in mind that it only works for variables and not other types or parameters (like $1, $#, $-) or array or association elements. There's also a grey areas if locale changes along the life of the shell. For instance, a script starting with: #! /bin/bash - export LC_ALL=C could have a number of variables inherited from the environment that are no longer usable because their name no longer are valid identifiers. declare -p $'\xe9' For instance may report true because there was a $é variable in the environment and the locale was for instance fr_FR.iso885915@euro. But that $\xe9 variable (though defined) is no longer accessible in the script since \xe9 is not a valid identifier in the C locale. For reference and comparison, in zsh: - arrays are a different type from scalars and are not sparse - $array expands to the non-empty elements in the array (and not ${array[0]} like in ksh/bash). You still need "${array[@]}" for all the elements. - $hash returns all the non-empty values in the hash (and not ${hash["0"]} like in ksh93 or bash) - ${scalar[n]} expands to the nth character in $scalar (and not the empty string (unless n == 0) in ksh/bash). - $+var expands to 1 if $var is defined, 0 otherwise, works for variables, array or hash elements and positional parameters. (($+var)) && echo var is set - $#array, $#hash, $#scalar expand to the number of elements in $array and $hash and number of characters in $scalar. (($#var)) && echo var not empty - ${(t)var} expands to the type (and attributes) of that variable. - $parameters is a special hash in the zsh/parameters module with that same information. $ echo $parameters[parameters] association-readonly-hide-hideval-special -- Stephane