Come posso rimuovere completamente un elemento da un array?


48

unset array[0]rimuove l'elemento ma comunque se lo faccio echo ${array[0]}ottengo un valore nullo inoltre ci sono altri modi per farlo ma se un elemento di un array contiene spazi come sotto

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

ma anche questi non riescono a fare il lavoro

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

ora voglio che il nuovo array sia simile

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

Gli spazi causano il problema dopo l'assegnazione e l'array reale diventa come con la sostituzione.

array=(mary randy orton)

4
No, non gli spazi causano problemi, ma la mancanza di quotazioni.
arte

Risposte:


68

Usa la sintassi dell'array sull'assegnazione e cita la tua variabile:

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

Modifica in base alla domanda nel commento. Perché $@puoi usarlo in questo modo:

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

8
Nota che non rimuove il primo elemento ma l'elemento di indice 0 e riassegna gli indici. Se il primo elemento fosse su indice 12, non rimuoverà nulla ma riassegnerà gli indici in modo che ciò che una volta era su indice 12 sarà ora su indice 0. Probabilmente non è un problema nel caso del PO ma probabilmente dovrebbe essere notato per Referenza futura. Il comportamento è diverso con le zshcui matrici non sono rare contrariamente a ksh o bash.
Stéphane Chazelas,

3
Ciao @StephaneChazelas. Il singolare di "indici" è " indice ". Grazie per il tuo commento!
Steven Lu,

3
@manatwork - re: la tua modifica - perché non utilizzarla shift?
don_crissti,

1
@don_crissti, buon punto. Mi sono concentrato sulla differenza di indicizzazione e non ho pensato oltre. Aveva anche in mente la situazione in cui è necessario scartare una quantità variabile di oggetti, ad esempio per mantenere esattamente gli ultimi 3: array=("${array[@]: -3}")e set -- "${@: -3}". Così bloccato agli indici.
arte

1
shift $[$#-3]per gli ultimi 3 è probabilmente molto più veloce per$@
Tino l'

0

Questo mi ha fatto pensare. Il problema con sed / awk / tail è che sono linea per linea. Dopo aver eliminato la prima riga, è necessario scrivere tutte le altre righe dallo spazio modello al file.

  • Puoi usare i seguenti comandi per fare quello che vuoi in pochi secondi.
  • Questo scriverà l'intero file su un array.
  • Rimuovere la prima riga mentre la scarica nuovamente nel file.

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

Basta cambiare il largefilenome del file.


Perché non usare sed -i 1d largefileinvece? Questo funziona anche con file più grandi di RAM + swap
Tino

0

Per rimuovere un elemento in un determinato indice, possiamo usare unsete quindi fare una copia su un altro array. Solo unsetin questo caso non è richiesto. Poiché unsetnon rimuove l'elemento, imposta semplicemente una stringa nulla sull'indice particolare dell'array.

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]}"

L'output è

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[@]}
~                                                                                                                                                              
~                       

4
Sarebbe molto meglio se ci fosse qualcosa per spiegare come funziona e non solo un blocco di codice. E che dire delle tilde in fondo?
un CVn

3
Seriamente, hai ragione. Sembra che sia stato scritto da un teppista, ma grazie. Devo davvero intrufolarlo solo tra i giorni di servizio dell'hamburger.
MageProspero,

Se uno qualsiasi degli elementi di q contiene spazi, questo verrà suddiviso in più elementi.
William Everett,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.