¿Cómo puedo eliminar un elemento de una matriz por completo?


48

unset array[0]elimina el elemento pero aún así, si lo hago echo ${array[0]}, obtengo un valor nulo, además, hay otras formas de hacerlo, pero si un elemento de una matriz contiene espacios como el siguiente

array[0]='james young'
array[1]='mary'
array[2]='randy orton'

pero estos tampoco hacen el trabajo

array=${array[@]:1} #removed the 1st element

ahora quiero que la nueva matriz sea como

array[0]='mary'
array[1]='randy orton'

Los espacios causan el problema después de la asignación y la matriz real se vuelve como con la sustitución.

array=(mary randy orton)

44
No, no los espacios causan problemas, sino la falta de citas.
manatwork

Respuestas:


68

Simplemente use la sintaxis de matriz en la asignación y cite su variable:

array=("${array[@]:1}") #removed the 1st element

Edite según la pregunta en el comentario. Para $@que pueda usarlo así:

set -- "${@:2}" #removed the 1st parameter

8
Tenga en cuenta que no elimina el primer elemento, sino el elemento del índice 0 y reasigna los índices. Si el primer elemento estaba en el índice 12, no eliminará nada, pero reasignará los índices de modo que lo que una vez estuvo en el índice 12 ahora estará en el índice 0. Probablemente no sea una preocupación en el caso del OP, pero probablemente debería tenerse en cuenta referencia futura. El comportamiento es diferente con zshcuyos arreglos no son escasos, al contrario de ksh o bash.
Stéphane Chazelas 18/03/2013

3
Hola @StephaneChazelas. El singular de "índices" es " índice ". ¡Gracias por tu comentario!
Steven Lu

3
@manatwork - re: tu edición - ¿por qué no usar shift?
don_crissti

1
@don_crissti, buen punto. Me concentré en la diferencia de indexación y no pensé más. También tenía en cuenta la situación en la que necesita descartar una cantidad variable de elementos, por ejemplo, para mantener exactamente los últimos 3: array=("${array[@]: -3}")y set -- "${@: -3}". Tan atrapado en los índices.
manatwork

1
shift $[$#-3]para los últimos 3 es probablemente mucho más rápido para$@
Tino

0

Esto me hizo pensar. El problema con sed / awk / tail es que son línea por línea. Después de eliminar la primera línea, debe escribir cada dos líneas desde el espacio del patrón al archivo.

  • Puede usar los siguientes comandos para hacer lo que quiera en segundos.
  • Esto escribirá el archivo completo en una matriz.
  • Elimine la primera línea ya que la vuelve a volcar en el archivo.

    readarray -t aLargeFile < <(cat largefile)
    echo "${aLargeFile[@]:1}" >largefile

Simplemente cambie el largefilenombre de su archivo.


¿Por qué no usar sed -i 1d largefileen su lugar? Esto incluso funciona para archivos más grandes que RAM + swap
Tino

0

Para eliminar un elemento en un índice particular, podemos usar unsety luego copiar a otra matriz. Solo unsetque no se requiere en este caso. Debido a unsetque no elimina el elemento, simplemente establece una cadena nula para el índice particular en la matriz.

declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in ${arr[@]}
do
    arr2[$i]=$element
    ((++i))
done
echo ${arr[@]}
echo "1st val is ${arr[1]}, 2nd val is ${arr[2]}"
echo ${arr2[@]}
echo "1st val is ${arr2[1]}, 2nd val is ${arr2[2]}"

La salida es

aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd

-1
#!/bin/bash

q=( one two three four five )

echo -e "
  (remove) { [:range:] } <- [:list:]
                | [:range:] => return list with range removed range is in the form of [:digit:]-[:digit:]
"

function remove {
  if [[ $1 =~ ([[:digit:]])(-([[:digit:]]))?   ]]; then
    from=${BASH_REMATCH[1]}
    to=${BASH_REMATCH[3]}
  else
    echo bad range
  fi;shift
  array=( ${@} )
  local start=${array[@]::${from}}
  local rest
  [ -n "$to" ] && rest=${array[@]:((${to}+1))}  || rest=${array[@]:((${from}+1))}
  echo ${start[@]} ${rest[@]}
}

q=( `remove 1 ${q[*]}` )
echo ${q[@]}
~                                                                                                                                                              
~                       

44
Esto sería mucho mejor si hubiera algo para explicar cómo funciona y no solo una gota de código. ¿Y qué pasa con las tildes en la parte inferior?
un CVn

3
En serio, tienes razón. Parece que fue escrito por un gamberro, pero gracias. Realmente solo puedo pasar esto entre los días de servicio de hamburguesas.
MageProspero

Si algún elemento de q tiene espacios, esto lo dividirá en múltiples elementos.
William Everett
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.