연관 배열이 많지만 루프를 1개만 사용하고 싶습니다. 주어진 이름으로 루프 배열 선택
변수를 사용하여 배열 이름의 일부를 선택/구축한 다음 해당 이름으로 반복하고 싶지만 작동하지 않습니다.
OUTPUT3 및 OUTPUT4와 유사하지만 구문이 잘못되었습니다.
출력 3의 경우 "bash error replacement"가 표시됩니다.
출력 4의 경우 "배열 이름만 있고 0"이 표시됩니다.
#!/bin/bash
clear
declare -A a1 a2 a3
a1['1']="1-1V"
a2['1']="2-1V"
a2['2']="2-2V"
a3['1']="3-1V"
a3['2']="3-2V"
a3['3']="3-3V"
# 1 OUTPUT WORKS
for i in ${!a1[*]}
do
echo -e "$i : ${a1[$i]}"
done
# 2 OUTPUT WORKS
for i in ${!a2[*]}
do
echo -e "$i : ${a2[$i]}"
done
# 3 OUTPUT - WRONG SYNTAX
selectkey="3"
for i in ${!a$selectkey[@]}
do
echo -e "$i : ${a$selectkey[$i]}"
done
# 4 OUTPUT - WRONG SYNTAX
key="3"
aselect="a${key}[*]"
# THIS ECHO WORKS
echo -e "ARRAY: ${!aselect}"
for i in ${!aselect[@]}
do
echo -e "$i : ${aselect[$i]}"
done
고쳐 쓰다
해결책은 nameref
|declare -n
이것은 지금 나에게 효과적입니다.
#!/bin/bash
clear
declare -A a1 a2 a3
a1['1']="1-1V"
a2['1']="2-1V"
a2['2']="2-2V"
a3['1']="3-1V"
a3['2']="3-2V"
a3['3']="3-3V"
varname="a3"
counter=1
declare -n refname=${varname}
for i in "${!refname[@]}"
do
echo -e "$counter ${refname[$counter]}"
counter=$((counter+1))
done
답변1
"nameref" 사용: declare -n a=b
변수를 a
변수의 별칭으로 만듭니다 b
.
# 3 OUTPUT - use a "nameref"
selectkey="3"
declare -n ary="a$selectkey"
for i in "${!ary[@]}"
do
echo "$i : ${ary[$i]}"
done
산출
3 : 3-3V
2 : 3-2V
1 : 3-1V
연관 배열은 본질적으로 순서가 없습니다.
#4의 경우 에 설명된 대로 "간접 확장"을 사용하고 있습니다.쉘 매개변수 확장하지만 이 기술을 사용하여 배열의 인덱스를 가져올 수는 없습니다.
답변2
bash
다차원 배열이 없습니다. 그러나 연관 배열과 키 연결( 결합된 문자열로 표시 key1
) 을 사용하여 구현할 수 있습니다. 여기 몇 가지 예가 있어요.key2
key1,key2
시작 시나리오를 고려하면
declare -A a
a[1,1]='1-1V'
a[2,1]='2-1V' a[2,2]='2-2V'
a[3,1]='3-1V' a[3,2]='3-2V' a[3,3]='3-3V'
모든 a[1,*]
값:
for i in $(printf "%s\n" "${!a[@]}" | awk -F, -vk='1' '$1==k {print $2}')
do
printf "%s: %s\n" "$i" "${a[1,$i]}"
done
산출
1: 1-1V
모든 a[*,2]
값:
for i in $(printf "%s\n" "${!a[@]}" | awk -F, -vk='2' '$2==k {print $1}')
do
printf "%s: %s\n" "$i" "${a[$i,2]}"
done
산출
3: 3-2V
2: 2-2V
키 세트를 생성하는 또 다른 방법:
for i in $(printf "%s\n" "${!a[@]}" | awk -F, -vk='1' '$2==k')
do
printf "%s: %s\n" "$i" "${a[$i]}";
done
산출
1,1: 1-1V
3,1: 3-1V
2,1: 2-1V
모든 경우에 키는 숫자 순서대로 되어 있지 않습니다. 필요한 경우 printf | awk
파이프를 전달하도록 구성을 수정할 수 있습니다 sort -n
(숫자 키 가정).
awk
필드 번호와 원하는 키 값을 지정하도록 구성을 일반화할 수도 있습니다 . 이는 아마도 함수에서 키 생성을 숨김으로써 캡슐화에 도움이 될 것입니다.
awk -F, -vfield=2 -vkey=1 '$field==key'
답변3
인덱스가 숫자인 경우 연관 배열보다는 일반 배열을 사용하는 것이 더 좋습니다. 둘 다 희박할 수 있지만 일반 배열을 사용하면 숫자 순서로 키를 반복할 수 있는 반면 연관 배열을 사용하면 본질적으로 무작위입니다. (다른 언어에서는 희소 배열을 얻으려면 연관 배열이 필요할 수도 있습니다.) 비교:
$ declare -A a=([11]=a [22]=b [33]=c )
$ echo "${a[@]}"
b a c
$ declare -a b=([11]=a [22]=b [33]=c)
$ echo "${b[@]}"
a b c
그런 다음 인덱스가 숫자이고 배열이 희박하지 않은 경우 연관 배열을 사용하여 2D 배열을 가짜로 만들고 수동으로 반복하여 인덱스를 반복할 수 있습니다.
declare -A a
a[1,1]="1-1V"
a[2,1]="2-1V"
a[2,2]="2-2V"
a[3,1]="3-1V"
a[3,2]="3-2V"
a[3,3]="3-3V"
x=3
i=1
while [[ ${a[$x,$i]+set} == set ]]; do
echo "${a[$x,$i]}"
((i++))
done
(물론 "존재하지 않음" 요소를 특정 값으로 설정한 다음 루프 내에서 해당 값을 무시하여 희소 배열을 시뮬레이션할 수 있습니다.)
Ksh는 실제로 2D 배열 또는 최소한 중첩 목록도 지원합니다.
a[1][1]="1-1V"
a[2][1]="2-1V"
a[2][2]="2-2V"
a[3][1]="3-1V"
a[3][2]="3-2V"
a[3][3]="3-3V"
x=3
for x in "${a[x][@]}"; do
echo "$x"
done
이것이 작동하지 않더라도:
for x in "${a[@][1]}"; do
echo "$x"
done
그러나 복잡한 데이터 구조에 대한 필요성은 셸에서 다른 프로그래밍 언어로 전환하는 것을 고려하는 것이 유용할 수 있는 상황 중 하나입니다.
${!array[*]}
어떠한 경우에도 , 또는 ${!array[@]}
( 포함 또는 제외 !
)을 사용하면 안 됩니다 . "${!array[@]}"
그 반대입니다. 공백이 포함된 값을 그대로 유지하는 유일한 방법이기 때문입니다. 예 z=("foo bar" "zoom")
를 들어 다음을 사용하여 for x in ${z[*]}; do echo $x; done
동일한 것과 비교하십시오."${z[*]}"
"${z[@]}"