bash 非数组 ${!name[@]} 参数扩展混乱
bash non-array ${!name[@]} parameter expansion confusion
鉴于 Bash Reference Manual in section 3.5.3 Shell Parameter Expansion
说:
${!name[@]}
${!name[*]}
If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to 0 if name is set and null otherwise. When ‘@’ is used and the expansion appears within double quotes, each key expands to a separate word.
和
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
和
${parameter:+word}
If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
有人可以向我解释以下扩展的输出吗:
$ 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[@]}
扩展本身的扩展方式?
在语法 ${!f[@]}
中,参数扩展被解析为 "list the keys" 表达式,这是 {!
引入间接级别的规则的特定例外之一.语法 ${!f[@]:-b}
与该模式不匹配(因为它以 :-b
结尾),因此 !
被解释为间接引用,因此它是 name 是 f
的值的变量,它正在被默认值修饰符测试。
有趣的问题是,"what does the [@]
modify in that expression?" 似乎在修改 f
,当 f
是标量时它什么都不做,但当 f
是时产生无效名称一个以上元素的数组;在这种情况下,似乎会发生默认值替换。
我最好的猜测是,这是一个未记录且可能是无意的参数扩展极端情况。
鉴于 Bash Reference Manual in section 3.5.3 Shell Parameter Expansion
说:
${!name[@]} ${!name[*]}
If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to 0 if name is set and null otherwise. When ‘@’ is used and the expansion appears within double quotes, each key expands to a separate word.
和
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
和
${parameter:+word}
If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
有人可以向我解释以下扩展的输出吗:
$ 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[@]}
扩展本身的扩展方式?
在语法 ${!f[@]}
中,参数扩展被解析为 "list the keys" 表达式,这是 {!
引入间接级别的规则的特定例外之一.语法 ${!f[@]:-b}
与该模式不匹配(因为它以 :-b
结尾),因此 !
被解释为间接引用,因此它是 name 是 f
的值的变量,它正在被默认值修饰符测试。
有趣的问题是,"what does the [@]
modify in that expression?" 似乎在修改 f
,当 f
是标量时它什么都不做,但当 f
是时产生无效名称一个以上元素的数组;在这种情况下,似乎会发生默认值替换。
我最好的猜测是,这是一个未记录且可能是无意的参数扩展极端情况。