Estoy intentando eliminar el rango de elementos de la matriz pero falla.
mi matriz
root@ubuntu:~/work# echo ${a[@]}
cocacola.com airtel.com pepsi.com
Imprimir la matriz 0-1 se ve bien
root@ubuntu:~/work# echo ${a[@]::2}
cocacola.com airtel.com
Ahora estoy intentando eliminar solo estos elementos usando:
root@ubuntu:~/work# unset a[@]::2
root@ubuntu:~/work# echo ${a[@]}
Es eliminar toda la matriz.
¿Qué estoy haciendo mal?
Encontré otra forma de eliminar un rango de matriz, pero ¿por qué lo anterior no funciona?
for ((i=0; i<2; i++)); do unset a[$i]; done
EDITAR También lo intenté pero no tuve suerte.
unset -v 'a[@]::2'
Respuesta1
Una cosa a tener en cuenta es que bash
se implementaron matrices como ksh
, es decir, matrices asociativas donde las claves se limitan a números enteros positivos (a diferencia de otros lenguajes como perl
o, zsh
por ejemplo).
En:
a[123]=foo a[456]=bar a[789]=baz
En bash, tienes una matriz asociativa con 3 elementos, mientras que en perl
, tendrías una matriz con 790 elementos (789 con zsh).
En ksh
o bash
, ${a[@]:0:1}
devuelve el primer elemento de la matriz en la lista de elementos ordenados numéricamente por clave donde la clave es mayor o igual a 0. Entonces, en ese caso, devuelve ${a[123]}
, no ${a[0]}
.
unset 'a[123]'
(recuerde citarlo, de lo contrario fallaría si hubiera un archivo llamado a1 o a2 o a3 en el directorio actual) tiene sentido, ya que elimina una clave particular en la matriz.
unset 'a[@]::2'
Aunque tiene menos sentido. bash
solo entiende unset a
, unset 'a[123]'
o unset 'a[*/@]'
, cualquier cosa posterior se ignora, así que unset 'a[@]::2'
haga unset 'a[@]please'
lo mismo: desarme toda la matriz.
Si desea desarmar un rango de claves, deberá recorrer las claves:
Para obtener la lista de claves de la matriz, la sintaxis es "${!a[@]}"
. Desafortunadamente, aplicar un rango a eso no funciona con bash
nor ksh
, por lo que necesitarías una matriz temporal:
keys=("${!a[@]}")
for i in "${keys[@]::2}"; do unset "a[$i]"; done
Ahora bien, si desea considerar esas matrices como en otros idiomas, no desea usar unset
. Por ejemplo, si la matriz no es escasa en primer lugar y desea mantenerla así (es decir, desplazar todos los elementos en 2 en lugar de desarmar los dos primeros), puede hacer cosas como:
a=("${a[@]:2}")
Eso es reasignar la matriz con la lista de elementos que desea conservar.
A modo de comparación, con zsh
.
a=({1..20})
unset 'a[12,16]'
establecería un valor vacío para los elementos 12 a 16. mientras que unset 'a[16,20]'
reduciría la matriz a 15 elementos.
a=({1..20})
a[12,16]=()
(aún con zsh
) desplazaría los elementos 17 a 20 en 5 posiciones, por lo que a[12]
contendría 17
.
Respuesta2
Si tu matriz escontinuo/no escaso(todos los elementos del conjunto 0..N-1)
Puede eliminar el segundo elemento de la matriz con
unset 'a[1]'
Para eliminar el segundo, tercer y cuarto elemento, puede utilizar, por ejemplo
for ((i=1; i<=3; i++)); do unset "a[$i]"; done
Para eliminar todos los elementos menos el primero y el segundo, puede usar, por ejemplo
for ((i=2; i<${#a[@]}; i++)); do unset "a[$i]"; done
solución general(funciona también para matrices dispersas): puede eliminar el segundo elemento de la matriz con
unset "a[$(echo ${!a[@]} | cut -d" " -f 2)]"
Para eliminar el segundo, tercer y cuarto elemento, puede utilizar, por ejemplo
for $(echo ${!a[@]} | cut -d" " -f 2-4) ; do unset "a[$i]"; done
Para eliminar todos los elementos menos el primero y el segundo, puede usar, por ejemplo
for $(echo ${!a[@]} | cut -d" " -f 2-) ; do unset "a[$i]"; done