Bashで配列の要素を削除
BashでもZshでもunset
を使って定義した変数を削除出来ますが、
Bashだと、配列の各要素も削除できます。
$ arr=(a "b c" "d e" f)
$ echo ${#arr[@]}
4
$ for i in {0..3};do echo "arr[$i]=${arr[$i]}";done
arr[0]=a
arr[1]=b c
arr[2]=d e
arr[3]=f
$ unset arr[2]
$ echo ${#arr[@]}
3
$ for i in {0..3};do echo "arr[$i]=${arr[$i]}";done
arr[0]=a
arr[1]=b c
arr[2]=
arr[3]=f
$ arr=("${arr[@]}")
$ for i in {0..3};do echo "arr[$i]=${arr[$i]}";done
arr[0]=a
arr[1]=b c
arr[2]=f
arr[3]=
ただし、削除するとその番号の要素が消えるだけで番号は詰められません。
詰めるためにはarr=("${arr[@]}")
的なことをして詰めなおして上げる必要があります
1。
Zshで配列の要素を削除
Zshだと配列の各要素に対してはunset
は使えません。
$ arr=(a "b c" "d e" f)
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=d e
arr[4]=f
$ unset arr[3]
zsh: no matches found: arr[3]
こんな感じエラーになります 2。
ちょっと調べた感じ直接消す方法がなさそう?だったんですが、 こんな感じでやったら上手くいきました。
$ arr=(a "b c" "d e" f)
$ echo ${#arr}
4
$ n=3
$ arr=(${arr[1,((n-1))]} ${arr[((n+1)),-1]})
$ echo ${#arr}
3
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=f
arr[4]=
Zshだと${arr[i,j]}
の形でi~jの要素を取り出せるので、
nより前と後をそれぞれ置いてるだけです。
ちょっと引っかかった所は、最初、前後の二つのそれぞれを"
で
囲ってやろうとしたら全体が1つとして認識されてしまった点。
上の様に"
は無しできちんと中身が(b c
なども)分割されます。
Zshの場合は@
/*
などの時も"
無しできちんとこの辺分割されます。
*
を使った時に"
で囲った時だけ全体が1つとして捉えられます。
${arr[i,j]}
みたいにした場合は*
と同じ様な扱いになるみたいで、
囲ってしまうと全体が1つとして捉えられてしまいます。
また、Bashで$arr
みたいにすると0番目の要素が参照されますが、
Zshだと${arr[*]}
とした時と同じ様になるみたいです(少なくとも下の例では)。
$ arr_orig=(a "b c" "d e" f)
$ arr=("${arr_orig[@]}")
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=d e
arr[4]=f
$ arr=(${arr_orig[@]})
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=d e
arr[4]=f
$ arr=(${arr_orig[*]})
$ for i in {0..3};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=d e
arr[4]=f
$ arr=("${arr_orig[*]}")
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a b c d e f
arr[2]=
arr[3]=
arr[4]=
$ arr=("${arr_orig[*]}")
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=d e
arr[4]=f
$ arr=("$arr_orig")
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a b c d e f
arr[2]=
arr[3]=
arr[4]=
$ arr=($arr_orig)
$ for i in {1..4};do echo "arr[$i]=${arr[$i]}";done
arr[1]=a
arr[2]=b c
arr[3]=d e
arr[4]=f
Bash/Zshで文字列の部分取得
配列のついでに文字列の部分取得について。
Bashでは少なくとも手元で一番古い3.2.25では
$ word="abcdefg"
$ echo ${word: 2: 3}
cde
とすれば2番目(最初の文字は0番)から3つの文字が表示されます。
同じくZshでもVersionが5以上であれば(取り敢えず手元の5.0.2では) 同じ事が出来ます。
ただ、古い4のバージョンの場合
zsh: unrecognized modifier `2'
と言ったエラーになってしまいます。
この場合、上の配列で使った部分取得の方法で
$ echo ${word[3,5]}
cde
この様にすれば同じ値が取れます。この場合は3番目から5番目まで、の取得で、 さらに最初の文字が1番なので上のBashの場合と区別が必要です。
ちょっと古い場所で使う場合には注意。
-
蛇足ですが、
()
内では""
で囲われた要素("b c"
など)が正しく1つとして 扱われる様に*
でなく@
を使ってさらに全体を"
で囲う必要があります。*
を使えば外側の"
で囲われた部分が全体が1つとして、 外側の"
が無ければ@
でも*
でも中の要素が空白(もしくはIFS)で切られるので bとcが別要素になってしまいます。 -
Zshの場合は通常配列が1から始まります:
それから、上の例ではBash同様
${arr[$i]}
みたいに使ってますが、 Zshではこの{
}
を消して$arr[$i]
と書くことも出来ます。${#arr}
も$#arr
でOK。