myFunc(){
parse "$1" && #parse() is a test
eval " shift #$1 is a valid, eval-safe name
local name$1 ${1#=}="'("$@")' #$1 is expanded before shift
}
parse()
case ${1#=} in
("$1"|""|[0-9]*|*[!_[:alnum:]]*) ! : #return false for all invalid names
esac
It does also work without eval given another execution step or two:
myFunc(){
local -a "name$1[@]" "${1#=}"='("${@:2}")' &&
[ -z "${1%=*}" ] && printf %s\\n "${!name}"
}
In that case I just allow the local builtin to do all of the validation and assignment at once. Basically, if the local command can assign "${1#=}"=("${@#"$1"}") successfully and "${1%=*}" is null then you know the assignment has taken place successfully. Any syntax error - such as bad shell names - will automatically fail and return with error during the local assignment, and the simple validation [ test ] which follows is all that is necessary to ensure that you don't accidentally do local name=morename=("${@#"$1"}").
The natural upshot to this is that when a bad name is passed in as =$1 the shell will automatically print out a meaningful error message to stderr for you and do all of the error handling automatically with no fuss.
Like this:
myFunc =goodname 1 2 3 'and some ;more' &&
myFunc =bad-name 1 2 3 'and some ;more'
1
2
3
and some ;more
bash: local: `bad-name=("${@:2}")': not a valid identifier
Note that doing functionname(){list;} is almost definitely not what you mean to do.
If you intend to localize the function's traps and similar you need functionname{list;}.
If you intend to share all state but your locally defined variables with the current shell then functionname(){list;} or name()list are equivalent because the function keyword is ignored by the shell (except that some shells which implement it tend to parse the following list incorrectly if it is not contained in curly braces) when name is followed by ().
"$@"instead of plain$@. Also, you don't need to quote'bar'and'baz', but, as long as you are doing so, you should probably quote=RESULT_PREF, too, to make it clear that you're treating it as just a string parameter.