Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 不使用eval的间接寻址_Arrays_Bash_Indirection - Fatal编程技术网

Arrays 不使用eval的间接寻址

Arrays 不使用eval的间接寻址,arrays,bash,indirection,Arrays,Bash,Indirection,我正在寻找一种干净的方法(不使用eval命令)来间接引用数组。以下是我想要的更精确的描述: 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)

我正在寻找一种干净的方法(不使用eval命令)来间接引用数组。以下是我想要的更精确的描述:

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?
}
具有以下调用值:

a=("a" "aa" "aaa")
b=("b" "bb" "bbb")
valueof a
valueof b
我得到的结果是:

indirection1 $a=a
indirection2 $a=a aa aaa
a
aa
aaa
indirection1 $b=b
indirection2 $b=b bb bbb
b
bb
bbb
关于标准:

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

感谢您对这个问题的回答/评论:)

我建议从git-devel分支构建Bash,并像大多数其他带数组的sane shell一样使用
typeset-n
。所有其他涉及函数和数组的解决方案都需要
eval
或利用古怪的未记录行为。两者都需要同等的照顾,而且两者之间不一定有优势

这里有一个通用的例子,它演示了几乎所有不需要评估就可以间接执行的操作。名称空间冲突仍然是可能的

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
isSubset(){
local-a'xkeys=(“${!”“$1”[@]}”)'ykeys=(“${!”“$2”[@]}”)'
设置--“${@/%/[key]}”

(${#xkeys[@]}顺便说一句,您的错误是由于ksh的不幸设计决定造成的,该决定使用前缀和后缀作为扩展运算符,而bash继承了这一点,并为间接寻址创建了自己的冲突使用
前缀(在其他shell中还有另一个与间接寻址相关的冲突使用).
“${!var[@]}”
意味着扩展var的键列表,并获得比
${!var}
更高的优先级。好的,感谢您的精确性。这就是为什么在您的代码中我们可以看到类似于
“$1”
的内容,以便首先扩展该部分?部分,但它也利用了一些血淋淋的细节,而不是使用参数的方式在Bash中有条件地解析“声明命令”,以便在某些条件下获得类似eval的双重扩展(这不是bug)。正在使用的其他间接方法是隐式算术变量间接方法,并利用间接将下标语法视为参数名的一部分。这些方法都不是真正“受支持”的,我花了太多时间来发现它,以便编写更好的可重用库(没有人能解释)