2017-03-17 17:35:36 -0500, Dan Douglas: > The need to localize IFS is pretty obvious to me - of course that's > given prior knowledge of how it works. [...]
I don't expect the need to have to add "local var" in ( unset -v var echo "${var-OK}" ) would be obvious to many people beside you though. People writing function libraries meant to be used by several POSIX-like shells need to change their code to: split() ( [ -z "$BASH_VERSION" ] || local IFS # WA for bash bug^Wmisfeature unset -v IFS set -f split+glob $1 ) if they want them to be reliable in bash. > The problem is the non-obvious nature of unset's interaction with scope, the main problem to me is an unset command that doesn't unset. As shown in my original post, there's also a POSIX conformance issue. > (and the lack of documentation). Not much can be done about the former, > as it is with so many things. So what should the documentation be? With my "eval" case in mind, it's hard to explain without getting down to how stacking variables work. Maybe something like: after unset -v var - if var had been declared (without -g) in the current function scope (not the global scope), $var becomes unset in the current scope (not in parent scopes). Futher unset attempts will not affect the variable in parent scopes. - otherwise, the previous var value (and type and attributes) is popped from a stack. That stack is pushed every time the variable is declared without -g in a new function scope or when the "." or "eval" special builtins are invoked as var=x eval 'code' or var=x . sourced-file. If the stack was empty, the variable is unset. There's also missing documentation for: unset -v 'var[x]' (note the need to quote that glob) can only be used if "var" is an array or hash variable and unsets the array/hash element of key x. Unsetting the last element does not unset the variable. For arrays, negative subscripts are relative to the greatest assigned subscript in the array. unset "a[-1]" "a[-1]" unsets the 2 elements with the greatest subscript, but that's not necessarily the case for unset "a[-2]" "a[-1]" if the array was sparse. unset "var[@]" or unset "var[*]" can be used to unset all the elements at once. For associative arrays, use unset 'a[\*]' or unset 'a[\@]' to unset the elements of key * and @. It is not possible [AFAICT] to unset the element of key "]" or where the key consists only of backslash characters [btw, it also looks like bash hashes (contrary to zsh or ksh93 ones) can't have an element with an empty key] It is not an error to attempt to "unset" a variable or array element that is not set, except when using negative subscripts. Also, the doc says: > The -v flag specifies that NAME refers to parameters. > This is the default behaviour. It might be worth pointing out that "unset -v", contrary to the default behaviour, won't unset functions so it's a good idea to use "unset -v" instead of "unset" if one can't guarantee that the variable was set beforehand (like the common case of using unset to remove a variable which was potentially imported from the environment). -- Stephane