解释本地-a' xkeys =(" $ {!'" $ 1"' [@]}")'

时间:2014-06-04 03:25:49

标签: arrays bash indirection

此代码作为bash-hackers.org wiki page的数组间接寻址的解决方法,作为间接获取数组长度和索引的示例。

Stackoverflow question中也提到过。

我想具体理解为什么local -a 'xkeys=("${!'"$1"'[@]}")'有效。这里发生了什么。我知道等号右边有三个不同的字符串:

  1. ' xkeys =("!$ {'
  2. " $ 1和#34;
  3. ' [@]}&#34)'
  4. 为什么这样做?

    这是代码:

    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
    }
    

    由于

2 个答案:

答案 0 :(得分:1)

${!"$1"}获取$1中命名的变量。 ${variable[@]}扩展为数组variable中的所有元素。所以这基本上将$1命名的数组复制到xkeys

答案 1 :(得分:1)

@tripleee基本上是正确的,虽然遗漏了一个细节(我在几分钟之前在我的答案here中写下我对其余isSubset的解释时也犯了同样的错误。)< / p>

这里的关键细节是local(以及declaretypeset)执行拥有解析其参数。

让我们来看看这一行的各种扩展

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也是如此)。

例如echoe() { 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的索引。