我有一个像菜单一样的程序。它有一个关联数组,称为config
:
declare -A config=( [h]="?" [c]="?" [x]="?" [l]="?" [t]="?" [n]="?" )
在主循环中,会检查所有值是否已配置,例如:
if [ "${config[h]}" == "Y" ] && [ "${config[c]}" == "Y" ] && [ "${config[l]}" == "Y" ] && [ "${config[x]}" == "Y" ] && [ "${config[t]}" == "Y" ] && [ "${config[n]}" == "Y" ];
现在,当我结束一次运行,我取消设置并重新声明数组。
unset config; declare -A config=( [h]="?" [c]="?" [x]="?" [l]="?" [t]="?" [n]="?" )
但是,该数组似乎没有正确重新声明。这是因为当我配置时一的值,[C]=Y
例如,if
语句通过。我肯定知道它确实如此,因为语句的正文if
改变了一些文本颜色。我相信这是因为其余索引实际上并未设置为“?”,因此该if
语句被简化为[ "${config[c]}" == "Y"]
is be true
。我知道这一点,因为当我$config[@]
在声明正文中回显时if
,果然我只看到一“Y”而不是五个。如何正确地重新声明数组?
编辑
感谢您的关注;
在一些用户输入后,值设置为 Y。这部分我非常有信心,因此从我的问题中省略了。它们都遵循以下格式:
read ch if [ $ch == "Hosts" ]; then while true; do nano listHosts echo -en "Commit this list of Hostnames? [Y|N to re-edit]: " read yn if [ $yn == "Y" ] || [ $yn == "y" ] || [ $yn == "yes" ]; then break elif [ $yn == "N" ] || [ $yn == "n" ] || [ $yn == "no" ]; then continue fi done config[h]="Y"
关于 Kusalanda 的评论,我检查了大小写是否正确,但它始终是小写的“c”。另外,是的,我的意思是
${config[@]}
。Declare -p 提供了一些启示:
declare -a config='([0]="Y")'
为什么 -p 说我用的是小写 a?调用顺序如下:
unset config
declare -A config=( [h]="?" [c]="?" [x]="?" [l]="?" [t]="?" [n]="?" )
read
然后我通过;设置 $ch="Commands"
elif [ $ch == "Commands" ]; then
while true; do
nano iSet
echo -en "Commit this list of commands? [Y|N to re-edit]: "
read yn
if [ $yn == "Y" ] || [ $yn == "y" ] || [ $yn == "yes" ]; then
break
elif [ $yn == "N" ] || [ $yn == "n" ] || [ $yn == "no" ]; then
continue
fi
done
config[c]="Y"
declare -p config
我尝试按照博多的建议在较小的脚本中重新创建:
dec() {
declare -A config=( [h]="?", [c]="?" )
}
test() {
declare -p config
if [ "${config[h]}" == "Y" ] && [ "${config[c]}" == "Y" ]; then
echo "Yup"
fi
}
dec
config[h]="Y"; config[c]="Y"
unset config
dec
config[h]="Y"
test
就像在我的其他脚本中一样,if
解析为 true:
declare -a config='([0]="Y")' Yup
答案1
您必须使用 将该数组声明为函数中的全局数组declare -g ...
。否则数组将是局部变量在函数中。看https://unix.stackexchange.com/a/136721/330217
请参阅此修改后的脚本以及一些调试输出
#! /bin/bash
# set -x
dec() {
# declare -A config=( [h]="?", [c]="?" )
declare -gA config=( [h]="?" [c]="?" )
echo dec: ${config[*]}
}
test() {
declare -p config
if [ "${config[h]}" == "Y" ] && [ "${config[c]}" == "Y" ]; then
echo "Yup"
else
echo "No"
fi
echo test: ${config[*]}
}
dec
echo 1: ${config[*]}
config[h]="Y"; config[c]="Y"
echo 2: ${config[*]}
test
unset config
dec
echo 3: ${config[*]}
config[h]="Y"
echo 4: ${config[*]}
test
输出是
$ ./script
dec: ? ?
1: ? ?
2: Y Y
declare -A config=([c]="Y" [h]="Y" )
Yup
test: Y Y
dec: ? ?
3: ? ?
4: ? Y
declare -A config=([c]="?" [h]="Y" )
No
test: ? Y
当我取消注释您的行并注释我修改后的行时,输出为
$ ./script
dec: ? ?,
1:
2: Y
declare -a config=([0]="Y")
Yup
test: Y
dec: ? ?,
3:
4: Y
declare -a config=([0]="Y")
Yup
test: Y
复制自 @ilkkachu 的评论:
当然,在关联数组的本地声明超出范围后,赋值
config[h]="Y"
会创建一个常规数组,其中索引在算术上下文中解释,其中h
(递归地)扩展变量的值h
,这可能不是设置后,您会得到计算结果为零的空字符串,因此它config[0]
被设置了。并且没有错误消息,因为set -u
它没有生效。
declare -a config=([0]="Y")
这可以在原始脚本的输出中看到。