메뉴와 같은 프로그램이 있습니다. 여기에는 다음과 같은 연관 배열이 있습니다 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". 배열을 올바르게 다시 선언하는 방법은 무엇입니까?
편집하다
관심을 가져주셔서 감사합니다.
일부 사용자 입력 후 값은 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"
쿠살란다 님의 댓글에 대해 대소문자가 맞는지 확인해봤는데 항상 소문자 "c" 네요. 또한, 그렇습니다. 내 말은
${config[@]}
…-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
다른 스크립트와 마찬가지로 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
. 경우를 설정한 후 0으로 평가한 결과를 얻으므로 빈 문자열이config[0]
설정됩니다. 그리고set -u
적용되지 않기 때문에 오류 메시지도 없습니다 .
declare -a config=([0]="Y")
이는 원본 스크립트의 출력에서 볼 수 있습니다.