다양한 배열 요소를 제거하려고 하는데 실패합니다.
내 배열
root@ubuntu:~/work# echo ${a[@]}
cocacola.com airtel.com pepsi.com
0-1 배열 인쇄가 괜찮아 보입니다.
root@ubuntu:~/work# echo ${a[@]::2}
cocacola.com airtel.com
이제 다음을 사용하여 이러한 요소만 제거하려고 합니다.
root@ubuntu:~/work# unset a[@]::2
root@ubuntu:~/work# echo ${a[@]}
전체 배열을 삭제합니다.
내가 뭘 잘못했나요?
배열 범위를 제거하는 다른 방법을 찾았지만 위의 방법이 작동하지 않는 이유는 무엇입니까?
for ((i=0; i<2; i++)); do unset a[$i]; done
편집 나도 시도했지만 운이 없었습니다
unset -v 'a[@]::2'
답변1
명심해야 할 한 가지는 이와 같은 배열이 즉, 키가 양의 정수로 제한되는 연관 배열로 bash
구현된다는 것 입니다( 또는 예를 들어 다른 언어와는 반대).ksh
perl
zsh
존재하다:
a[123]=foo a[456]=bar a[789]=baz
Bash에는 3개의 요소가 있는 연관 배열이 있는 반면, Bash에는 perl
790개의 요소(zsh의 경우 789개 요소)가 있는 배열이 있습니다.
ksh
또는 에서는 키가 0보다 크거나 같은 키를 기준으로 숫자로 정렬된 요소 목록에서 배열의 첫 번째 요소를 반환합니다 bash
. ${a[@]:0:1}
따라서 이 경우에는 ${a[123]}
대신 반환됩니다 ${a[0]}
.
unset 'a[123]'
(인용하는 것을 기억하세요. 그렇지 않으면 현재 디렉토리에 a1, a2 또는 a3이라는 파일이 있으면 실패합니다.) 배열에서 특정 키를 제거하기 때문에 의미가 있습니다.
unset 'a[@]::2'
그러나 그것은 큰 의미가 없습니다. , 또는 이후의 모든 항목은 무시 bash
되므로 동일한 작업을 수행합니다. 전체 배열을 설정 해제합니다 .unset a
unset 'a[123]'
unset 'a[*/@]'
unset 'a[@]::2'
unset 'a[@]please'
키 범위를 설정 해제하려면 키를 반복해야 합니다.
배열의 키 목록을 얻으려면 구문은 입니다 "${!a[@]}"
. 불행히도 적용 범위는 작동하지 않으므로 bash
임시 ksh
배열이 필요합니다.
keys=("${!a[@]}")
for i in "${keys[@]::2}"; do unset "a[$i]"; done
이제 이러한 배열을 다른 언어처럼 생각하고 싶다면 를 사용하고 싶지 않을 것입니다 unset
. 예를 들어 배열이 처음부터 희소하지 않았고 이를 희소하게 유지하려는 경우(예: 모든 요소를 2로 이동하고, 처음 두 개를 설정 해제하는 대신 다음을 수행할 수 있습니다.
a=("${a[@]:2}")
즉, 유지할 요소 목록으로 배열을 다시 할당합니다.
비교를 위해 zsh
.
a=({1..20})
unset 'a[12,16]'
요소 12~16은 null로 설정됩니다. while은 unset 'a[16,20]'
배열을 15개 요소로 축소합니다.
a=({1..20})
a[12,16]=()
(still zsh
)은 요소 17을 20의 5개 위치로 이동하므로 a[12]
포함됩니다 17
.
답변2
귀하의 배열이연속/비희소(0..N-1 그룹의 모든 요소)
다음을 사용하여 배열의 두 번째 요소를 삭제할 수 있습니다.
unset 'a[1]'
두 번째, 세 번째, 네 번째 요소를 제거하려면 다음을 사용할 수 있습니다.
for ((i=1; i<=3; i++)); do unset "a[$i]"; done
첫 번째와 두 번째 요소를 제외한 모든 요소를 제거하려면 다음을 사용할 수 있습니다.
for ((i=2; i<${#a[@]}; i++)); do unset "a[$i]"; done
범용 솔루션(희소 배열에도 작동): 다음을 사용하여 배열의 두 번째 요소를 제거할 수 있습니다.
unset "a[$(echo ${!a[@]} | cut -d" " -f 2)]"
두 번째, 세 번째, 네 번째 요소를 제거하려면 다음을 사용할 수 있습니다.
for $(echo ${!a[@]} | cut -d" " -f 2-4) ; do unset "a[$i]"; done
첫 번째와 두 번째 요소를 제외한 모든 요소를 제거하려면 다음을 사용할 수 있습니다.
for $(echo ${!a[@]} | cut -d" " -f 2-) ; do unset "a[$i]"; done