副教授。数组没有被重新声明?

副教授。数组没有被重新声明?

我有一个像菜单一样的程序。它有一个关联数组,称为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”而不是五个。如何正确地重新声明数组?

编辑
感谢您的关注;

  1. 在一些用户输入后,值设置为 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"
    
  2. 关于 Kusalanda 的评论,我检查了大小写是否正确,但它始终是小写的“c”。另外,是的,我的意思是${config[@]}

  3. 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")这可以在原始脚本的输出中看到。

相关内容