我正在寻找一种干净的方法(无需 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 并使用typeset -n
就像大多数其他带有数组的理智 shell 一样。所有其他涉及函数和数组的解决方案都需要eval
或利用古怪的无证行为。两者都需要同等的照顾,并且其中一方不一定比另一方有优势。
这是一个一般示例,它演示了无需 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
这真的是eval
在某些方面是变相的。大多数人都没有意识到,每当他们将变量名传递给内置函数和算术表达式时,他们都在有效地执行 eval。您必须始终确保变量名称和索引受到内部控制,并且不会受到用户输入或您无法保证结果的其他副作用的影响。
从您对分词和引用的滥用来看,您可能应该切换到另一种语言。 Bash 并不是真正要处理安全封装的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)