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行目でstdoutが空白になっているのはなぜですか。12行目のstdoutで配列が更新されているように見えるのを考えてみてください。
したがって、意図された回答「69」を取得するにはどうすればよいですか?
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では、配列のインデックスが連続している必要はありません。
要素4
のないnumbers
配列から始めましょう:
$ 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
があり、値は69
です。
もう一度、numbers
を定義しましょう:
$ numbers=(53 8 12 9 784 69 8 7 1)
コメントの Toby Speight で示唆されているように、4番目の要素を削除し、残りの要素の番号を1つのステップですべて再設定する方法:
$ 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")
ご覧のとおり、4番目の要素が削除され、残りのすべての要素の番号が付け直されました。
${numbers[@]:0:4}
スライス配列numbers
:要素0から始まる最初の4つの要素を取得します。
同様に、${numbers[@]:5}
スライス配列numbers
:要素5で始まり、配列の最後まで続くすべての要素を取ります。
配列のvaluesは${a[@]}
で取得できます。これらの値に対応するindices(またはkeys)を見つけるには、${!a[@]}
を使用します。
たとえば、要素4
のない配列numbers
をもう一度考えてみます。
$ 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]
は、インデックスsubscript
の配列要素を破棄します。インデックス付き配列への負の添え字は、上記のように解釈されます。パス名の展開による不要な副作用を回避するように注意する必要があります。unset name
、ここでname
は配列、またはunset name[subscript]
、ここでsubscript
は*
または@
は、アレイ全体。
bash
のような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
/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})
ksh
およびbash
次の場合、配列を通常の配列として使用できます。
a=("${a[@]}")
インデックスのリストが連続していないか、0で始まらない可能性がある各削除または挿入操作の後。ksh
/bash
配列は1ではなく0で始まることに注意してください($@
(いくつかの方法で))。
これにより、要素が整理され、インデックス0、1、2 ...に順に移動します。
また、number[i]
を引用符で囲む必要があることに注意してください。
unset 'number[i]'
それ以外の場合は、現在のディレクトリにnumberi
というファイルがあった場合、unset numberi
として扱われます。