Как я могу полностью удалить элемент из массива?


48

unset array[0]удаляет элемент, но все же, если я это сделаю, echo ${array[0]}я получаю нулевое значение, более того, есть другие способы сделать это, но если элемент массива содержит пробелы, как показано ниже

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

но они также не в состоянии сделать работу

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

теперь я хочу, чтобы новый массив был похож

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

Пробелы вызывают проблемы после присваивания, и фактический массив становится похожим на подстановку.

array=(mary randy orton)

4
Нет, не пробелы вызывают проблемы, а отсутствие цитирования.
manatwork

Ответы:


68

Просто используйте синтаксис массива в присваивании и укажите вашу переменную в кавычках:

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

Редактировать в соответствии с вопросом в комментарии. Ибо $@вы можете использовать это так:

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

8
Обратите внимание, что он удаляет не 1-й элемент, а элемент индекса 0 и переназначает индексы. Если первый элемент был на индексе 12, он ничего не удалит, но переназначит индексы, так что то, что раньше было на индексе 12, теперь будет на индексе 0. Это, вероятно, не является проблемой в случае ОП, но, вероятно, следует отметить будущая ссылка. Поведение отличается от того, zshчьи массивы не редки, в отличие от ksh или bash.
Стефан Шазелас

3
Привет @StephaneChazelas. Единственное число «индексов» это « индекс ». Спасибо за ваш комментарий!
Стивен Лу

3
@manatwork - re: ваше редактирование - почему бы не использовать shift?
don_crissti

1
@don_crissti, хорошая мысль. Я сосредоточился на разнице в индексировании и не думал дальше. Также имелась в виду ситуация, когда нужно отбросить переменное количество предметов, например, чтобы сохранить точно последние 3: array=("${array[@]: -3}")и set -- "${@: -3}". Так что застрял на индексах.
Манатворк

1
shift $[$#-3]для последних 3, вероятно, гораздо быстрее для$@
Тино

0

Это заставило меня задуматься. Проблема с sed / awk / tail в том, что они построчно. После того, как вы удалите первую строку, вы должны записать каждую вторую строку из пространства шаблона в файл.

  • Вы можете использовать следующие команды, чтобы сделать то, что вы хотите в считанные секунды.
  • Это запишет весь файл в массив.
  • Удалите первую строку, так как она возвращает ее обратно в файл.

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

Просто измените largefileимя вашего файла.


Почему бы не использовать sed -i 1d largefileвместо этого? Это даже работает для файлов больше, чем RAM + swap
Tino

0

Чтобы удалить элемент по определенному индексу, мы можем использовать unsetи затем сделать копию в другой массив. Только просто unsetне требуется в этом случае. Поскольку unsetне удаляет элемент, он просто устанавливает нулевую строку для определенного индекса в массиве.

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

Выход

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
Было бы намного лучше, если бы было что объяснить, как это работает, а не просто кусок кода. А что с тильдами внизу?
CVN

3
Серьезно, вы правы. Похоже, это было написано хулиганом, но спасибо. Я действительно только крадусь между гамбургерами.
MageProspero

Если в любом элементе q есть пробелы, это разбьет его на несколько элементов.
Уильям Эверетт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.