Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash非数组${!name[@]}参数扩展混乱_Bash_Shell - Fatal编程技术网

bash非数组${!name[@]}参数扩展混乱

bash非数组${!name[@]}参数扩展混乱,bash,shell,Bash,Shell,鉴于本节中的说明: 如果名称是数组变量,则展开为在名称中指定的数组索引(键)列表。如果名称不是数组,则在设置名称时扩展为0,否则扩展为null。当使用“@”且展开显示在双引号内时,每个键都会展开为一个单独的单词 及 ${参数:-word} 如果参数为unset或null,则替换word的展开形式。否则,将替换参数的值 及 ${参数:+word} 如果参数为null或unset,则不替换任何内容,否则替换word的展开形式 有人能给我解释一下以下扩展的输出吗: $ bash --version G

鉴于本节中的说明:

如果名称是数组变量,则展开为在名称中指定的数组索引(键)列表。如果名称不是数组,则在设置名称时扩展为0,否则扩展为null。当使用“@”且展开显示在双引号内时,每个键都会展开为一个单独的单词

${参数:-word}

如果参数为unset或null,则替换word的展开形式。否则,将替换参数的值

${参数:+word}

如果参数为null或unset,则不替换任何内容,否则替换word的展开形式

有人能给我解释一下以下扩展的输出吗:

$ 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:  :