Bagaimana cara menghapus elemen dari array sepenuhnya?

48

unset array[0]menghapus elemen tetapi tetap jika saya lakukan echo ${array[0]}saya mendapatkan nilai null apalagi ada cara lain untuk melakukan ini tetapi jika elemen array berisi spasi seperti di bawah ini

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

tetapi ini juga gagal melakukan pekerjaan

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

sekarang saya ingin seperti array baru

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

Spasi menyebabkan masalah setelah penugasan dan array aktual menjadi seperti dengan substitusi.

array=(mary randy orton)
munish
sumber
4
Tidak, bukan spasi yang menyebabkan masalah, tetapi kurangnya kutipan.
manatwork

Jawaban:

68

Cukup gunakan sintaks array pada tugas dan kutip variabel Anda:

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

Edit menurut pertanyaan dalam komentar. Untuk $@Anda bisa menggunakannya seperti ini:

set -- "${@:2}" #removed the 1st parameter
manatwork
sumber
8
Perhatikan bahwa itu tidak menghapus elemen 1 tetapi elemen indice 0 dan menugaskan kembali indeks. Jika elemen pertama adalah pada indice 12, itu tidak akan menghapus apa pun tetapi akan menugaskan kembali indeks sehingga apa yang dulu di indice 12 sekarang berada di indice 0. Mungkin bukan masalah dalam kasus OP tetapi mungkin perlu dicatat untuk referensi di masa depan. Perilaku ini berbeda dengan zsharray yang jarang bertentangan dengan ksh atau bash.
Stéphane Chazelas
3
Hai @StephaneChazelas. Satu "indeks" adalah " indeks ". Terima kasih atas komentar Anda!
Steven Lu
3
@manatwork - re: edit Anda - mengapa tidak menggunakan shift?
don_crissti
1
@don_crissti, poin bagus. Saya fokus pada perbedaan pengindeksan dan tidak berpikir lebih jauh. Juga perlu diingat situasi ketika Anda harus membuang jumlah item yang bervariasi, misalnya untuk tetap mempertahankan 3 terakhir: array=("${array[@]: -3}")dan set -- "${@: -3}". Jadi terjebak pada indeks.
manatwork
1
shift $[$#-3]untuk 3 terakhir mungkin jauh lebih cepat untuk$@
Tino
0

Ini membuat saya berpikir. Masalah dengan sed / awk / tail adalah bahwa mereka baris demi baris. Setelah Anda menghapus baris pertama Anda harus menulis setiap baris lainnya dari ruang pola ke file.

  • Anda dapat menggunakan perintah berikut untuk melakukan apa yang Anda inginkan dalam hitungan detik.
  • Ini akan menulis seluruh file ke sebuah array.
  • Hapus baris pertama karena akan mengembalikannya ke file.

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

Ubah saja largefileke nama file Anda.

jgshawkey
sumber
Kenapa tidak digunakan sed -i 1d largefilesaja? Ini bahkan berfungsi untuk file yang lebih besar dari RAM + swap
Tino
0

Untuk menghapus elemen pada indeks tertentu, kita dapat menggunakan unsetdan kemudian menyalin ke array lain. Hanya saja unsettidak diperlukan dalam kasus ini. Karena unsettidak menghapus elemen itu hanya menetapkan string nol ke indeks tertentu dalam 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]}"

Output adalah

aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd
rashok
sumber
-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[@]}
~                                                                                                                                                              
~                       
MageProspero
sumber
4
Ini akan jauh lebih baik jika ada sesuatu untuk menjelaskan cara kerjanya dan bukan hanya gumpalan kode. Dan ada apa dengan tildes di bagian bawah?
CVn
3
Serius, kamu benar. Ini memang terlihat seperti ditulis oleh hooligan, tapi terima kasih. Aku benar-benar hanya bisa menyelinap di antara hamburger ini selama berhari-hari.
MageProspero
Jika ada elemen q yang memiliki spasi di dalamnya, ini akan memecahnya menjadi beberapa elemen.
William Everett