bash非数组${!name[@]}参数扩展混乱
鉴于本节中的说明: 如果名称是数组变量,则展开为在名称中指定的数组索引(键)列表。如果名称不是数组,则在设置名称时扩展为0,否则扩展为null。当使用“@”且展开显示在双引号内时,每个键都会展开为一个单独的单词 及 ${参数:-word} 如果参数为unset或null,则替换word的展开形式。否则,将替换参数的值 及 ${参数:+word} 如果参数为null或unset,则不替换任何内容,否则替换word的展开形式 有人能给我解释一下以下扩展的输出吗:bash非数组${!name[@]}参数扩展混乱,bash,shell,Bash,Shell,鉴于本节中的说明: 如果名称是数组变量,则展开为在名称中指定的数组索引(键)列表。如果名称不是数组,则在设置名称时扩展为0,否则扩展为null。当使用“@”且展开显示在双引号内时,每个键都会展开为一个单独的单词 及 ${参数:-word} 如果参数为unset或null,则替换word的展开形式。否则,将替换参数的值 及 ${参数:+word} 如果参数为null或unset,则不替换任何内容,否则替换word的展开形式 有人能给我解释一下以下扩展的输出吗: $ bash --version G
$ 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: :
这就是为什么所讨论的变量的内容会改变
${!name[@]:-default}
和${!name[@]:+alt}
扩展的方式,当内容没有改变${!name[@]}
扩展本身如何扩展时?在语法${!f[@]}
中,参数扩展被解析为“列出键”表达式,这是规则的特定例外之一,{!
引入了一个间接级别。语法${!f[@]:-b}
与该模式不匹配(因为它以:-b
结尾),因此,!
被解释为一个间接引用,因此它是由默认值修饰符测试的变量,其名称是f
的值
有趣的问题是,“在这个表达式中,[@]
修改了什么?”它似乎在修改f
,当f
是标量时,它什么也不做,但当f
是一个包含多个元素的数组时,它会生成一个无效的名称;在这种情况下,似乎会发生默认值替换
我最好的猜测是,这是一个未记录的、可能是无意中的参数扩展的角落案例。啊,你是在暗示shell正在做
${!f[@]:-b}
>${f[@]:-b}
${!f[@]:-b}${t[@]:-b}
,然后(有效地)忽略[@]
${与${not_array}
相同,然后看到${f:-b}
或${t:-b}
?这不是我第一次希望在shell中有一个分步扩展调试标志。@EtanReisner:如果在测试中设置了f=t=u
,你会看到什么?但我不知道[@]
正被忽略。它似乎只有在f
是标量的情况下才被忽略。Afaics,如果f是数组,即使是一个元素,间接寻址也会失败,默认值被替换。t
,0
,u
,b
,这四个扩展符合您的解释。是的,我是sp具体地说,[@]
的标量/非数组情况被忽略(我也不理解,但这是另一个问题)。数组情况是正常值扩展(符合您看到的和我期望的)。我没有尝试过使用数组进行间接/扩展,因为当时我没有使用数组。是的,我想我自己很困惑。如果f
是一个数组,并且您设置了f=value
,那么您实际上是在分配f[0]
,而不是将f
变回标量。我想我知道这一点,但在我测试你的表达式时,它并没有警告我。所以我只是在没有[@]
的情况下测试了相同的扩展,结果是相同的(显然是0
->t
,等等,在${code>{!f}
case。看来你是对的(我并不感到惊讶)。我希望你能注意到我的问题,这样我就不必去戳语法分析器或诸如此类的疯狂行为了。=)
$ 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: :