부교수. 배열이 다시 선언되지 않습니까?

부교수. 배열이 다시 선언되지 않습니까?

메뉴와 같은 프로그램이 있습니다. 여기에는 다음과 같은 연관 배열이 있습니다 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일부 텍스트 색상을 변경하기 때문에 그렇게 된다는 것을 확실히 알고 있습니다. 이는 나머지 인덱스가 실제로 "?"로 설정되지 않았기 때문이라고 생각하므로 명령문은 is be if로 단순화 됩니다 . 나는 명령문 본문에 에코할 때 확실히 나는 단지 볼 수만 있기 때문에 이것을 알고 있습니다.[ "${config[c]}" == "Y"]true$config[@]if하나5 대신 "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. 쿠살란다 님의 댓글에 대해 대소문자가 맞는지 확인해봤는데 항상 소문자 "c" 네요. 또한, 그렇습니다. 내 말은 ${config[@]}

  3. -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

Bodo가 제안한 대로 더 작은 스크립트로 다시 만들려고 했습니다.

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

다른 스크립트와 마찬가지로 iftrue로 확인됩니다. 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. 경우를 설정한 후 0으로 평가한 결과를 얻으므로 빈 문자열이 config[0]설정됩니다. 그리고 set -u적용되지 않기 때문에 오류 메시지도 없습니다 .

declare -a config=([0]="Y")이는 원본 스크립트의 출력에서 ​​볼 수 있습니다.

관련 정보