Indirection without using eval

家住魔仙堡 提交于 2019-12-11 00:27:37

问题


I'm looking for a clean way (without eval command) to do an indirect reference to an array. Here is a more precise description of what I want :

function valueof {
   echo "indirection1 \$$1=${!1}"
   eval "echo indirection2 \\\$$1=\${$1[@]}" # Untill this step its fine.

   # My final objective is to do this (but eval is not a very sexy solution) : 
   for i in $(eval "echo \${$1[@]}") ; do 
      echo $i
   done

   # Here is the "problem", ie. "bad substitution"
   echo "indirection3 \$$1=${!1[@]}"  
   # "1[@]" is evaluated first i guess?
}

With the following valueof calls :

a=("a" "aa" "aaa")
b=("b" "bb" "bbb")
valueof a
valueof b

The output I have is :

indirection1 $a=a
indirection2 $a=a aa aaa
a
aa
aaa
indirection1 $b=b
indirection2 $b=b bb bbb
b
bb
bbb

On stderr :

prog.sh: line 10: indirection3 $1=${!1[@]}: bad substitution
prog.sh: line 10: indirection3 $1=${!1[@]}: bad substitution

Thanks for your answers/remarks on this question :)


回答1:


I suggest building Bash from the git devel branch and using typeset -n like most other sane shells with arrays do. All other solutions involving functions and arrays require either eval or exploiting quirky undocumented behaviours. Both require about equal care and there isn't necessarily an advantage to one over the other.

Here is a general example which demonstrates just about everything you can do indirectly without eval. Namespace collisions are still possible.

isSubset() {
    local -a 'xkeys=("${!'"$1"'[@]}")' 'ykeys=("${!'"$2"'[@]}")'
    set -- "${@/%/[key]}"

    (( ${#xkeys[@]} <= ${#ykeys[@]} )) || return 1

    local key
    for key in "${xkeys[@]}"; do
        [[ ${!2+_} && ${!1} == "${!2}" ]] || return 1
    done
}

a=(abc def [4]=ghi jkl)
b=(abc def [4]=ghi jkl)
c=(abc [3]=def [6]=ghi xyz)
isSubset a b
echo $? # 0
isSubset b c
echo $? # 1

This is really eval in disguise in some respects. Most people are unaware that they are effectively performing eval any time they pass variable names to builtins and arithmetic expressions. You have to always ensure that variable names and indexes are controlled internally and never influenced by user input or other side-effects that you can't guarantee the results of.

Judging by your misuse of wordsplitting and quoting, you should probably just switch to a different language. Bash isn't really meant to deal with safe encapsulation.



来源:https://stackoverflow.com/questions/13541465/indirection-without-using-eval

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!