1. ホーム
  2. arrays

[解決済み] Bash配列から要素を削除する

2022-05-01 23:30:57

質問

bashシェルで配列から要素を削除する必要があります。 一般的に私は単純にそうします。

array=("${(@)array:#<element to remove>}")

残念ながら、削除したい要素は変数なので、前のコマンドは使えません。 この下はその例です。

array+=(pluto)
array+=(pippo)
delete=(pluto)
array( ${array[@]/$delete} ) -> but clearly doesn't work because of {}

何か心当たりは?

どのように解決するのですか?

で思い通りに動作します。 bashzsh :

$ array=(pluto pippo)
$ delete=pluto
$ echo ${array[@]/$delete}
pippo
$ array=( "${array[@]/$delete}" ) #Quotes when working with strings

複数の要素を削除する必要がある場合。

...
$ delete=(pluto pippo)
for del in ${delete[@]}
do
   array=("${array[@]/$del}") #Quotes when working with strings
done

洞窟

このテクニックは、実際には、プレフィックスにマッチする $delete を要素から削除します。要素全体とは限りません。

更新

本当に正確な項目を削除するには、配列の中を歩き回って各要素とターゲットを比較し、その上で unset を使用して、完全に一致するものを削除します。

array=(pluto pippo bob)
delete=(pippo)
for target in "${delete[@]}"; do
  for i in "${!array[@]}"; do
    if [[ ${array[i]} = $target ]]; then
      unset 'array[i]'
    fi
  done
done

このようにして、1つ以上の要素が削除されると、インデックスは連続した整数の列ではなくなりますので、ご注意ください。

$ declare -p array
declare -a array=([0]="pluto" [2]="bob")

単純な話、配列は変更可能なデータ構造として設計されたものではありません。配列は主に、区切り文字として無駄な文字を使うことなく、1つの変数に項目のリストを格納するために使われます(例えば、空白を含むことができる文字列のリストを格納するため)。

隙間が問題になる場合は、隙間を埋めるように配列を再構築する必要があります。

for i in "${!array[@]}"; do
    new_array+=( "${array[i]}" )
done
array=("${new_array[@]}")
unset new_array