配列要素の範囲を削除しようとしていますが、失敗します。
私の配列
root@ubuntu:~/work# echo ${a[@]}
cocacola.com airtel.com pepsi.com
0-1配列を印刷すると問題ないようです
root@ubuntu:~/work# echo ${a[@]::2}
cocacola.com airtel.com
今、私は以下を使用してこれらの要素のみを削除しようとしています:
root@ubuntu:~/work# unset a[@]::2
root@ubuntu:~/work# echo ${a[@]}
配列全体を削除します。
何が間違っているのでしょうか?
配列の範囲を削除する他の方法を見つけましたが、上記の方法が機能しないのはなぜでしょうか?
for ((i=0; i<2; i++)); do unset a[$i]; done
編集 私も試してみましたが、運がありませんでした
unset -v 'a[@]::2'
答え1
覚えておくべきことの 1 つは、bash
のような実装された配列ksh
、つまりキーが正の整数に制限される連想配列であることです (たとえば や のような他の言語とは異なりますperl
) zsh
。
で:
a[123]=foo a[456]=bar a[789]=baz
bash では 3 つの要素を持つ連想配列が得られますが、 ではperl
790 個の要素 (zsh では 789 個) を持つ配列が得られます。
ksh
またはではbash
、${a[@]:0:1}
キーが 0 以上である、キーによって数値的にソートされた要素のリスト内の配列の最初の要素を返します。したがって、その場合は では${a[123]}
なく を返します${a[0]}
。
unset 'a[123]'
(引用符で囲むことを忘れないでください。そうしないと、現在のディレクトリに a1 または a2 または a3 というファイルがある場合に失敗します) は、配列内の特定のキーを削除するので意味があります。
unset 'a[@]::2'
ただし、あまり意味がありません。 は、または のみbash
を理解し、それ以降のものはすべて無視されるため、と は同じことを行います。つまり、配列全体を設定解除します。unset a
unset 'a[123]'
unset 'a[*/@]'
unset 'a[@]::2'
unset 'a[@]please'
キーの範囲を設定解除したい場合は、キーをループする必要があります。
配列のキーのリストを取得するには、構文は です"${!a[@]}"
。残念ながら、 に範囲を適用してもbash
や では機能しないksh
ため、一時的な配列が必要になります。
keys=("${!a[@]}")
for i in "${keys[@]::2}"; do unset "a[$i]"; done
ここで、他の言語のようにこれらの配列を考慮したい場合は、 を使用したくないはずですunset
。たとえば、配列がそもそもスパースではなく、その状態を維持したい場合 (つまり、最初の 2 つの要素を設定解除するのではなく、すべての要素を 2 ずつシフトする場合)、次のようにすることができます。
a=("${a[@]:2}")
つまり、保持したい要素のリストを配列に再割り当てします。
比較のために、 とzsh
。
a=({1..20})
unset 'a[12,16]'
は要素 12 から 16 に空の値を設定します。一方、unset 'a[16,20]'
は配列を 15 要素に縮小します。
a=({1..20})
a[12,16]=()
(まだzsh
) は要素 17 から 20 を 5 位置シフトするので がa[12]
含まれます17
。
答え2
配列が連続的/非散在的(0..N-1 セットのすべての要素)
配列の2番目の要素を削除するには
unset 'a[1]'
2番目、3番目、4番目の要素を削除するには、例えば次のようにします。
for ((i=1; i<=3; i++)); do unset "a[$i]"; done
1番目と2番目の要素以外をすべて削除するには、例えば次のようにします。
for ((i=2; i<${#a[@]}; i++)); do unset "a[$i]"; done
一般的な解決策(疎な配列でも機能します):配列の2番目の要素を削除するには、
unset "a[$(echo ${!a[@]} | cut -d" " -f 2)]"
2番目、3番目、4番目の要素を削除するには、例えば次のようにします。
for $(echo ${!a[@]} | cut -d" " -f 2-4) ; do unset "a[$i]"; done
1番目と2番目の要素以外をすべて削除するには、例えば次のようにします。
for $(echo ${!a[@]} | cut -d" " -f 2-) ; do unset "a[$i]"; done