【bashシェル】配列の要素を削除する時の注意


この記事はプロモーションを含みます。

bashシェル

ホーム > bashシェルスクリプト リファレンス

Shellの配列には、要素を削除してもインデックスはそのまま残るという仕様があります。
この仕様がどのようなものかを説明します。

配列にある要素削除時の仕様について

配列にある要素を削除してもインデックスが残ったままになります。
→文字列が存在しない(ブランク)値が残ったままになります。
実際にどのような状態になるのか見てみたいと思います。

以下は、2つ目の要素である「メロン」を削除した配列の内容を確認するシェルです。

#!/bin/bash
array=("りんご" "メロン" "ぶどう")
unset array[1]
echo -e "${array[0]}\n${array[1]}\n${array[2]}"

こちらのシェルを実行すると、りんごとぶどうの間にインデックスが残ったままになっていることが分かります。

[root@STKWPS001 ws]# sh test.sh
りんご

ぶどう
[root@STKWPS001 ws]#

これを回避するには、配列を詰めなおす必要があります。
以下が、要素の削除後に配列を詰めなおしたシェルです。

#!/bin/bash
array=("りんご" "メロン" "ぶどう")
unset array[1]
array=(${array[@]})
echo -e "${array[0]}\n${array[1]}\n${array[2]}"

こちらのシェルを実行すると、りんごとぶどうが連続で出力されるようになったことが分かります。
ブランクな要素が最後に移動しただけで、消えたわけではないのが気にはなりますが。。

[root@STKWPS001 ws]# sh test.sh
りんご
ぶどう

[root@STKWPS001 ws]#

配列を元にループした場合の挙動

配列から要素を削除し、その配列を元にループした場合にどのような挙動になるのか見てみます。

こちらは、配列の詰めなおしを行わないシェルです。

#!/bin/bash
array=("りんご" "メロン" "ぶどう")
unset array[1]

for item in ${array[@]}
do
	echo ${item}
done

実行結果です。削除した要素は無視されてループされるようです。

[root@STKWPS001 ws]# sh test.sh
りんご
ぶどう
[root@STKWPS001 ws]#

次に、配列の詰めなおしを行うシェルです。

#!/bin/bash
array=("りんご" "メロン" "ぶどう")
unset array[1]
array=("${array[@]}")

for item in ${array[@]}
do
	echo ${item}
done

実行結果です。

[root@STKWPS001 ws]# sh test.sh
りんご
ぶどう
[root@STKWPS001 ws]#

配列の詰めなおしの有無で実行結果は変わらないため、ループ処理する上では、インデックスが残ったままでも問題ないようです。

printコマンドで改行表示した場合の挙動

配列から要素を削除し、その配列を改行しつつ表示した場合にどのような挙動になるのか見てみます。

こちらは、配列の詰めなおしを行わないシェルです。

#!/bin/bash
array=("りんご" "メロン" "ぶどう")
unset array[1]

printf '%s\n' "${array[@]}"

実行結果です。削除した要素は無視されて処理されるようです。

[root@STKWPS001 ws]# sh test.sh
りんご
ぶどう
[root@STKWPS001 ws]#

次に、配列の詰めなおしを行うシェルです。

#!/bin/bash
array=("りんご" "メロン" "ぶどう")
unset array[1]
array=("${array[@]}")

printf '%s\n' "${array[@]}"

実行結果です。

[root@STKWPS001 ws]# sh test.sh
りんご
ぶどう
[root@STKWPS001 ws]#

配列の詰めなおしの有無で実行結果は変わらないため、インデックスが残ったままでも問題ないようです。

おわりに

今回は、要素を削除した場合に、インデックスがそのまま残るという仕様について説明しました。
ループ処理や改行表示しても問題なく動作するようですが、処理によっては正しく動作しない場合もあるかもしれません。
配列にはこのような仕様があるということを念頭に置いて頂ければ幸いです。

コメント

タイトルとURLをコピーしました