【问题标题】:bash non-array ${!name[@]} parameter expansion confusionbash 非数组 ${!name[@]} 参数扩展混淆
【发布时间】:2015-01-06 21:39:11
【问题描述】:

鉴于3.5.3 Shell Parameter Expansion 部分中的Bash Reference Manual 说:

${!name[@]}
${!name[*]}

如果 name 是一个数组变量,则扩展为 name 中分配的数组索引(键)列表。如果 name 不是一个数组,如果 name 被设置则扩展为 0,否则为 null。当使用“@”并且扩展出现在双引号内时,每个键都会扩展为一个单独的单词。

和

${参数:-word}

如果参数未设置或为空,则替换单词的扩展。否则,参数的值被替换。

和

${参数:+word}

如果参数为null或未设置,则不替换任何内容,否则替换单词的扩展。

有人可以向我解释以下扩展的输出吗:

$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
$ cat hm.sh
p() {
    printf "%-11s : f=%1s : " "$*" "$f"
    eval printf \'%1s :\\n\' "$@"
}

p '$f'
p '${!f[@]}'
p '${!f[@]:-b}'
echo "echo: ${!f[@]:-b} :"
p '${!f[@]:+b}'
echo "echo: ${!f[@]:+b} :"
f=f
p '$f'
p '${!f[@]}'
p '${!f[@]:-b}'
echo "echo: ${!f[@]:-b} :"
p '${!f[@]:+b}'
echo "echo: ${!f[@]:+b} :"
f=t
p '$f'
p '${!f[@]}'
p '${!f[@]:-b}'
echo "echo: ${!f[@]:-b} :"
p '${!f[@]:+b}'
echo "echo: ${!f[@]:+b} :"

$ bash hm.sh
$f          : f=  :   :
${!f[@]}    : f=  :   :
${!f[@]:-b} : f=  : b :
echo: b :
${!f[@]:+b} : f=  :   :
echo:  :
$f          : f=f : f :
${!f[@]}    : f=f : 0 :
${!f[@]:-b} : f=f : f :
echo: f :
${!f[@]:+b} : f=f : b :
echo: b :
$f          : f=t : t :
${!f[@]}    : f=t : 0 :
${!f[@]:-b} : f=t : b :
echo: b :
${!f[@]:+b} : f=t :   :
echo:  :

这就是为什么当内容不改变@987654328如何扩展时,所讨论变量的内容会改变${!name[@]:-default}和${!name[@]:+alt}扩展的扩展方式@ 扩展本身扩展?

【问题讨论】:

    标签: bash shell


    【解决方案1】:

    在语法${!f[@]} 中,参数扩展被解析为“列出键”表达式,这是{! 引入间接级别的规则的特定例外之一。语法${!f[@]:-b} 与该模式不匹配(因为它以:-b 结尾),所以! 被解释为间接引用,因此它是名称的变量 是f 的值,正在被默认值修饰符测试。

    有趣的问题是,“[@] 在那个表达式中修改了什么?”它似乎正在修改f,当f 是标量时它什么也不做,但当f 是一个以上元素的数组时会产生无效名称;在这种情况下,似乎会发生默认值替换。

    我最好的猜测是,这是参数扩展的一个未记录且可能意外的极端情况。

    【讨论】:

    • 啊,你是在暗示 shell 正在做 ${!f[@]:-b} -> ${f[@]:-b} 和 ${!f[@]:-b} -> ${t[@]:-b} 然后(有效地)忽略 [@] 作为 ${not_array[@]} 是与${not_array} 相同,然后看到${f:-b} 或${t:-b}?这不是我第一次希望在 shell 中有一个逐步扩展的调试标志。
    • @EtanReisner:如果在您的测试中设置f=t t=u,您会看到什么?但我不知道[@] 是否被完全忽略了。它似乎只在f 是标量的情况下被忽略。 Afaics,如果 f 是一个数组,即使是一个元素,间接失败并替换默认值。
    • t, 0, u, b 用于四个扩展,符合您的解释。是的,我专门讨论了 [@] 被忽略的标量/非数组情况(我也不明白,但这是一个不同的问题)。数组案例是正常值扩展(符合您所看到的和我所期望的)。我没有尝试过使用数组进行这种间接/扩展,因为那不是我当时正在玩的。
    • 是的,我想我自己弄糊涂了。如果f 是一个数组,而您设置了f=value,那么您实际上是在分配f[0],而不是将f 转换回标量。我想我在头脑的某个尘土飞扬的角落里知道这一点,但是当我测试你的表情时它并没有警告我。
    • 所以我只是测试了相同的扩展 without [@] 并且结果是相同的(显然与0 -> t 等在@987654355 @ case。看来你是对的(我并不感到惊讶)。我希望你能注意到我的问题,这样我就不必去戳解析器或类似的疯狂了。=)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多