Jak mogę całkowicie usunąć element z tablicy?


48

unset array[0]usuwa element, ale mimo to echo ${array[0]}otrzymuję wartość null, są też inne sposoby, ale jeśli element tablicy zawiera spacje takie jak poniżej

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

ale one również nie wykonują zadania

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

teraz chcę, żeby nowa tablica była jak

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

Spacje powodują problemy po przypisaniu, a rzeczywista tablica staje się jak z podstawieniem.

array=(mary randy orton)

4
Nie, nie spacje powodują kłopotów, ale brak cytowania.
manatwork

Odpowiedzi:


68

Wystarczy użyć składni tablicowej dla zadania i podać swoją zmienną:

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

Edytuj zgodnie z pytaniem w komentarzu. Dla $@można go używać tak:

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

8
Zauważ, że nie usuwa pierwszego elementu, ale element indeksu 0 i ponownie przypisuje indeksy. Jeśli pierwszy element był na indeksie 12, niczego nie usunie, ale ponownie przypisze indeksy, tak aby to, co kiedyś było na indeksie 12, będzie teraz na indeksie 0. Prawdopodobnie nie jest to problem w przypadku PO, ale prawdopodobnie należy to zauważyć przyszłe odniesienie. Zachowanie jest inne, w przypadku zshktórych tablice nie są rzadkie, w przeciwieństwie do ksh lub bash.
Stéphane Chazelas

3
Cześć @StephaneChazelas. Liczba pojedyncza „indeksów” to „ indeks ”. Dzięki za komentarz!
Steven Lu

3
@manatwork - re: twoja edycja - dlaczego nie używać shift?
don_crissti

1
@don_crissti, dobry punkt. Skoncentrowałem się na różnicy w indeksowaniu i nie zastanawiałem się więcej. Miał także na uwadze sytuację, w której musisz odrzucić zmienną liczbę przedmiotów, na przykład aby zachować dokładnie 3: array=("${array[@]: -3}")i set -- "${@: -3}". Tak utknąłem na indeksach.
manatwork

1
shift $[$#-3]dla ostatnich 3 jest prawdopodobnie znacznie szybszy dla$@
Tino

0

To mnie zastanowiło. Problem z sed / awk / tail polega na tym, że są one linia po linii. Po usunięciu pierwszego wiersza musisz zapisać co drugi wiersz ze przestrzeni wzorów do pliku.

  • Możesz użyć następujących poleceń, aby zrobić to, co chcesz w kilka sekund.
  • Spowoduje to zapisanie całego pliku do tablicy.
  • Usuń pierwszy wiersz, gdy zrzuca go z powrotem do pliku.

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

Po prostu zmień largefilenazwę pliku.


Dlaczego nie użyć sed -i 1d largefilezamiast tego? Działa to nawet w przypadku plików większych niż RAM + swap
Tino

0

Aby usunąć element z określonego indeksu, możemy użyć, unseta następnie skopiować do innej tablicy. Tylko unsetw tym przypadku nie jest wymagane. Ponieważ unsetnie usuwa elementu, ustawia po prostu łańcuch zerowy na konkretny indeks w tablicy.

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

Dane wyjściowe to

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
Byłoby znacznie lepiej, gdyby było coś, co wyjaśniłoby, jak to działa, a nie tylko kropla kodu. A co z tyldami na dole?
CVn

3
Poważnie, masz rację. Wygląda na to, że został napisany przez chuligana, ale dziękuję. Naprawdę mogę tylko przekraść się między dniami serwowania hamburgerów.
MageProspero,

Jeśli jakikolwiek element q ma w sobie spacje, spowoduje to rozbicie go na wiele elementów.
William Everett,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.