중간의 일부 인덱스에서 bash 배열을 어떻게 이동합니까?


12
1  #!/bin/bash
2  # query2.sh
3
4  numbers=(53 8 12 9 784 69 8 7 1)
5  i=4
6
7  echo ${numbers[@]} # <--- this echoes "53 8 12 9 784 69 8 7 1" to stdout.
8  echo ${numbers[i]} # <--- this echoes "784" to stdout.
9
10 unset numbers[i]
11
12 echo ${numbers[@]} # <--- this echoes "53 8 12 9 69 8 7 1" to stdout.
13 echo ${numbers[i]} # <--- stdout is blank.

13 행에서 12 행의 stdout에 의해 배열이 업데이트 된 것으로 보이면 stdout이 공백 인 이유는 무엇입니까?

따라서 "69"라는 정답을 얻으려면 어떻게해야합니까?


1
이 질문이 암시하는 코딩 작업의 유형을 고려할 때 경고를해야합니다. 내 스크립트에 문제가 있거나 Bash가 Python보다 훨씬 느립니까?를 참조하십시오.
와일드 카드

답변:


21

unset요소를 제거합니다. 나머지 요소의 번호는 변경하지 않습니다.

우리는 declare -p정확히 무슨 일이 일어나는지 볼 수 있습니다 numbers.

$ unset "numbers[i]"
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")

numbers더 이상 요소가 없는지 확인 하십시오 4.

다른 예시

관찰 :

$ a=()
$ a[1]="element 1"
$ a[22]="element 22"
$ declare -p a
declare -a a=([1]="element 1" [22]="element 22")

배열 a에는 요소 2-21이 없습니다. Bash에서는 배열 인덱스가 연속적 일 필요는 없습니다.

인덱스의 번호를 다시 매기도록 제안 된 방법

numbers누락 된 요소 가있는 배열 부터 시작하겠습니다 4.

$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")

지수를 변경하려면 다음을 수행하십시오.

$ numbers=("${numbers[@]}")
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [4]="69" [5]="8" [6]="7" [7]="1")

이제 요소 번호 4가 있으며 value 69입니다.

한 단계에서 요소를 제거하고 배열의 번호를 다시 매기는 다른 방법

다시 정의하자 numbers.

$ numbers=(53 8 12 9 784 69 8 7 1)

주석에서 Toby Speight 가 제안한 것처럼 네 번째 요소를 제거하고 나머지 요소의 번호를 한 번에 모두 다시 지정하는 방법입니다.

$ numbers=("${numbers[@]:0:4}" "${numbers[@]:5}")
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [4]="69" [5]="8" [6]="7" [7]="1")

보시다시피, 네 번째 요소가 제거되고 나머지 모든 요소의 번호가 다시 매겨졌습니다.

${numbers[@]:0:4}slices array numbers: 요소 0으로 시작하는 처음 4 개의 요소를 사용합니다.

마찬가지로 ${numbers[@]:5}slice 배열 numbers: 요소 5로 시작하여 배열 끝까지 모든 요소를 ​​가져옵니다.

배열의 인덱스 얻기

배열 의 은로 얻을 수 있습니다 ${a[@]}. 해당 값에 해당하는 인덱스 (또는 ) 를 찾으려면을 사용하십시오 ${!a[@]}.

예를 들어 numbers누락 된 요소가있는 배열 을 다시 고려하십시오 4.

$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")

할당 된 인덱스를 확인하려면

$ echo "${!numbers[@]}"
0 1 2 3 5 6 7 8

다시, 4지수 목록에서 누락되었습니다.

선적 서류 비치

보낸 사람 man bash:

unset내장 배열을 파괴하는 데 사용됩니다. unset name[subscript]index의 배열 요소를 삭제합니다 subscript. 인덱스 배열에 대한 음의 아래 첨자는 위에서 설명한대로 해석됩니다. 경로 이름 확장으로 인한 원하지 않는 부작용을 피하기 위해주의를 기울여야합니다. unset name여기서, name배열, 또는 unset name[subscript], 여기서 subscript이고 * 또는 @전체 어레이를 제거한다.


1
쉘 배열 구문은 실제로 비슷한 이름의 변수를 쉽게 처리 할 수있는 방법 일뿐입니다. 배열 자체 는 없습니다 . 실제로을 작성한 후에 실제로 해당 인덱스 중 하나에 할당 할 때까지 a=()변수 a는 정의되지 않습니다.
chepner

@ John1024 :이 답변에 감사드립니다. 의도 한 결과를 달성하기위한 제안 된 답변을 포함하도록 확장 할 수 있습니까?
Anthony Webber

@AnthonyWebber는 물론이다. 인덱스에 번호를 다시 매기는 방법을 보여주기 위해 답변에 섹션을 추가했습니다.
John1024

2
다른 접근법 (일부 코드에 더 적합 할 수 있음)을 언급하기 만하면 : 대신 unset numbers[4]슬라이싱을 사용하여 전체 배열을 할당하십시오 numbers=("${numbers[@]:0:4}" "${numbers[@]:5}")( 예 : 답변으로 게시하지만 올바르게 설명 할 시간이 없습니다).
Toby Speight

@ John1024 : 감사합니다. 그리고 thnx Toby :)
Anthony Webber

5

bashin과 같은 배열 ksh은 실제로 배열이 아니며, 양의 정수로 제한된 키 (또는 스파 스 배열 이라고도 함 )가있는 연관 배열과 비슷 합니다. 실제 어레이와 쉘의 경우, 같은 껍질에 모양을 가질 수 rc, es, fish, yash, zsh(또는 csh/ tcsh그 껍질이 너무 많은 문제가 있지만 그들은 더 나은 피할 것).

에서 zsh:

a=(1 2 3 4 5)
a[3]=() # remove the 3rd element
a[1,3]=() # remove the first 3 elements
a[-1]=() # remove the last element

(zsh에서는 unset 'a[3]'실제로와의 호환성을 향상시키기 위해 빈 문자열로 설정합니다. ksh)

에서 yash:

a=(1 2 3 4 5)
array -d a 3 # remove the 3rd element
array -d a 1 2 3 # remove the first 3 elements
array -d a -1 # remove the last element

에서 fish( bash/ 와 반대되는 Bourne과 같은 쉘이 zsh아님) :

set a 1 2 3 4 5
set -e a[3] # remove the 3rd element
set -e a[1..3] # remove the first 3 elements
set -e a[-1] # remove the last element

에서 es( rc본과 같지 않은 기반 )

a = 1 2 3 4 5
a = $a(... 2 4 ...) # remove the 3rd element
a = $a(4 ...) # remove the first 3 elements
a = $a(... `{expr $#a - 1}) # remove the last element
# or a convoluted way that avoids forking expr:
a = $a(... <={@{*=$*(2 ...); return $#*} $a})

에서 kshbash

다음과 같은 경우 배열을 일반 배열로 사용할 수 있습니다.

a=("${a[@]}")

인덱스 목록이 연속적이지 않거나 0에서 시작하지 않을 수있는 각 삭제 또는 삽입 조작 후. ksh/ bash배열은 1이 아닌 0에서 시작합니다 $@(일부 방법 제외).

실제로 요소를 정리하고 인덱스 0, 1, 2 ...로 순서대로 이동합니다.

또한 number[i]in 을 인용해야합니다 .

unset 'number[i]'

그렇지 않으면 현재 디렉토리에 unset numberi파일이있는 것처럼 취급됩니다 numberi.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.