Here's another revised version. I figured I could use bash internal `printf -v' just before the `eval' to check if the variable name is a valid identifier. This should be an exceptional case, so I don't mind doing this at the end of the function - checking just before the eval. Now it's also easy to see the eval is safe (provided you don't make typos on the right hand side, see http://mywiki.wooledge.org/BashFAQ/006, thanks).
I moved conflict checking to a central reusable function "_blackbox_safe_vars()" because one needs to do this for *every* library function which is returning variables by reference, in my opinion, unless you're willing to obfuscate all your local variables and still wait for a conflict to happen? The code below works around the following bash caveats?: - local variables conflict with variables to be returned by reference - `local' only lists variables having a value - `printf -v' can't be used to assign to an array Here's the code: # Check whether variable name(s) conflicts with local(s) # Params: $1 Local var names (output of 'local') # $* Variables to check # Return: False (1) if error _blackbox_safe_vars() { local IFS=$'\n' l v for l in $1; do for v in "${@:2}"; do [[ ${l%=*} == $v ]] && echo "ERROR: ${FUNCNAME[1]}:"\ "\`$v': conflicts with local" 1>&2 && return 1 done done return 0 } # Check whether private function is being called by public interface # Params: $1 Public function # Return: False (1) if error _blackbox_called_by() { [[ ${FUNCNAME[2]} != $1 ]] && { echo "ERROR: ${FUNCNAME[1]}:"\ "MUST be called by $1()" 1>&2; return 1; } || return 0 } # Private library function. Do not call directly. See blackbox() _blackbox() { _blackbox_called_by blackbox || return 1 local a b c d e f g h i j k=( foo "bar cee" ) # ... # Lots of library code here, not more than one screen though ;-) # ... printf -v"$2" %s b # Return value printf -v"$3" x && eval $3=\(\"\$...@]}\"\) # Return array return 0 # Return status } # Param: $1 input argument # Param: $2 variable name to return value to # Param: $3 variable name to return array value to # Public library function blackbox() { # NOTE: Give all locals a value so they're listed with 'local' local __2= __3= __x= _blackbox_safe_vars "$(local)" "$2" "$3" || return 1 _blackbox "$1" __2 __3 # Call private __x=$? # Catch status printf -v"$2" %s "$__2" # Return value printf -v"$3" x && eval $3=\(\"\${_...@]}\"\) # Return array return $__x # Return status } blackbox i a b; printf $'%s\n' $a "$...@]}" # Outputs vars ok blackbox i __2 __3 # Outputs error d='ls /;true'; blackbox i "$d" "$d" # No oops _blackbox a # Force public access Freddy Vulto http://fvue.nl/wiki/Bash:_passing_variables_by_reference