此代码作为bash-hackers.org wiki page的数组间接寻址的解决方法,作为间接获取数组长度和索引的示例。
此Stackoverflow question中也提到过。
我想具体理解为什么local -a 'xkeys=("${!'"$1"'[@]}")'
有效。这里发生了什么。我知道等号右边有三个不同的字符串:
为什么这样做?
这是代码:
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
}
由于
答案 0 :(得分:1)
${!"$1"}
获取$1
中命名的变量。 ${variable[@]}
扩展为数组variable
中的所有元素。所以这基本上将$1
命名的数组复制到xkeys
。
答案 1 :(得分:1)
@tripleee基本上是正确的,虽然遗漏了一个细节(我在几分钟之前在我的答案here中写下我对其余isSubset
的解释时也犯了同样的错误。)< / p>
这里的关键细节是local
(以及declare
和typeset
)执行拥有解析其参数。
让我们来看看这一行的各种扩展
local -a 'xkeys=("${!'"$1"'[@]}")' 'ykeys=("${!'"$2"'[@]}")'
现在拆分引用的部分将有助于理解。这让我们
local -a 'xkeys=("${!' "$1" '[@]}")' 'ykeys=("${!' "$2" '[@]}")'
扩展到
local -a 'xkeys=("${!' "a" '[@]}")' 'ykeys=("${!' "b" '[@]}")'
重新组装成
local -a 'xkeys=("${!'"a"'[@]}")' 'ykeys=("${!'"a"'[@]}")'
组合相邻的引用词语得到我们
local -a 'xkeys=("${!a[@]}")' 'ykeys=("${!a[@]}")'
如果除了local
之外什么都不行,我们就此完成了(ok eval
也是如此)。
例如echo
:e() { echo 'xkeys=("${!'"$1"'[@]}")' 'ykeys=("${!'"$2"'[@]}")'; }; e a b
输出xkeys=("${!a[@]}") ykeys=("${!b[@]}")
但是,因为这是local
,正如我之前所说,它自己进行解析(实际上你知道它已经存在,因为否则{0..5}
扩展到a
不会有用。请echo {0..5} vs. "{0..5}"
查看我的意思)单引号字符串由local
重新评估,并发生数组索引扩展。因此,${!a[@]}
扩展为a
的索引,${!b[@]}
扩展为b
的索引。