Estou tentando excluir o intervalo do elemento da matriz, mas falhou.
Minha matriz
root@ubuntu:~/work# echo ${a[@]}
cocacola.com airtel.com pepsi.com
Imprimir matriz 0-1 parece ok
root@ubuntu:~/work# echo ${a[@]::2}
cocacola.com airtel.com
Agora estou tentando excluir apenas esses elementos usando:
root@ubuntu:~/work# unset a[@]::2
root@ubuntu:~/work# echo ${a[@]}
É excluir toda a matriz.
O que estou fazendo de errado?
Encontrei outra maneira de excluir o intervalo do array, mas por que as coisas acima não estão funcionando?
for ((i=0; i<2; i++)); do unset a[$i]; done
EDIT Eu também tentei, mas sem sorte
unset -v 'a[@]::2'
Responder1
Uma coisa a ter em mente é que bash
arrays implementados como ksh
, isto é, arrays associativos onde as chaves são limitadas a números inteiros positivos (ao contrário de outras linguagens como perl
ou zsh
por exemplo).
Em:
a[123]=foo a[456]=bar a[789]=baz
No bash, você tem um array associativo com 3 elementos, enquanto no bash perl
você teria um array com 790 elementos (789 com zsh).
Em ksh
or bash
, ${a[@]:0:1}
retorna o primeiro elemento do array na lista de elementos ordenados numericamente por chave onde a chave é maior ou igual a 0. Portanto, nesse caso, ele retorna ${a[123]}
, não ${a[0]}
.
unset 'a[123]'
(lembre-se de citá-lo, caso contrário, falharia se houvesse um arquivo chamado a1 ou a2 ou a3 no diretório atual) faz sentido, pois remove uma chave específica da matriz.
unset 'a[@]::2'
faz menos sentido embora. bash
entende apenas unset a
, unset 'a[123]'
ou unset 'a[*/@]'
, qualquer coisa depois é ignorada, então unset 'a[@]::2'
e unset 'a[@]please'
faça o mesmo: desmarque todo o array.
Se você quiser desabilitar um intervalo de chaves, precisará percorrer as chaves:
Para obter a lista de chaves do array, a sintaxe é "${!a[@]}"
. Infelizmente, aplicar um intervalo a isso não funciona bash
nem ksh
, então você precisaria de um array temporário:
keys=("${!a[@]}")
for i in "${keys[@]::2}"; do unset "a[$i]"; done
Agora, se você quiser considerar esses arrays como em outras linguagens, não vai querer usar unset
. Por exemplo, se o array não for esparso em primeiro lugar e você quiser mantê-lo assim (isto é, mudar todos os elementos por 2 em vez de remover a configuração dos dois primeiros), você pode fazer coisas como:
a=("${a[@]:2}")
Isso é reatribuir o array com a lista de elementos que você deseja manter.
Para comparação, com zsh
.
a=({1..20})
unset 'a[12,16]'
definiria um valor vazio para os elementos 12 a 16. while unset 'a[16,20]'
reduziria a matriz para 15 elementos.
a=({1..20})
a[12,16]=()
(ainda com zsh
) mudaria os elementos 17 a 20 em 5 posições, portanto a[12]
conteria 17
.
Responder2
Se sua matriz forcontínuo/não esparso(todos os elementos do conjunto 0..N-1)
Você pode remover o segundo elemento da matriz com
unset 'a[1]'
Para remover o 2º, 3º e 4º elemento, você pode usar, por exemplo
for ((i=1; i<=3; i++)); do unset "a[$i]"; done
Para excluir todos, exceto o primeiro e o segundo elemento, você pode usar, por exemplo
for ((i=2; i<${#a[@]}; i++)); do unset "a[$i]"; done
Solução geral(funciona também para arrays esparsos): Você pode remover o segundo elemento do array com
unset "a[$(echo ${!a[@]} | cut -d" " -f 2)]"
Para remover o 2º, 3º e 4º elemento, você pode usar, por exemplo
for $(echo ${!a[@]} | cut -d" " -f 2-4) ; do unset "a[$i]"; done
Para excluir todos, exceto o primeiro e o segundo elemento, você pode usar, por exemplo
for $(echo ${!a[@]} | cut -d" " -f 2-) ; do unset "a[$i]"; done