Como posso remover completamente um elemento de uma matriz?


48

unset array[0]remove o elemento, mas ainda assim, se eu echo ${array[0]}receber um valor nulo, além disso, existem outras maneiras de fazer isso, mas se um elemento de uma matriz contiver espaços como abaixo

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

mas estes também não conseguem fazer o trabalho

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

agora eu quero que a nova matriz seja

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

Os espaços causam problemas após a atribuição e a matriz real se torna semelhante à substituição.

array=(mary randy orton)

4
Não, não os espaços causam problemas, mas a falta de citação.
manatwork

Respostas:


68

Basta usar a sintaxe da matriz na atribuição e citar sua variável:

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

Edite de acordo com a pergunta no comentário. Pois $@você pode usá-lo assim:

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

8
Observe que ele não remove o 1º elemento, mas o elemento do índice 0 e reatribui os índices. Se o primeiro elemento estava no índice 12, ele não removerá nada, mas irá reatribuir os índices para que o que antes estava no índice 12 agora esteja no índice 0. Provavelmente não é uma preocupação no caso do OP, mas deve ser notado por referência futura. O comportamento é diferente com zshcujas matrizes não são esparsas, ao contrário do ksh ou do bash.
Stéphane Chazelas 18/03/2013

3
Olá @StephaneChazelas. O singular de "índices" é " índice ". Obrigado por seu comentário!
Steven Lu

3
@manatwork - re: sua edição - por que não usar shift?
don_crissti

1
@don_crissti, bom ponto. Eu me concentrei na diferença de indexação e não pensei mais. Também teve em mente a situação em que você precisa descartar uma quantidade variável de itens, por exemplo, para manter exatamente os últimos 3: array=("${array[@]: -3}")e set -- "${@: -3}". Tão preso em índices.
manatwork

1
shift $[$#-3]nos últimos 3 é provavelmente muito mais rápido para$@
Tino

0

Isso me fez pensar. O problema com o sed / awk / tail é que eles são linha por linha. Depois de excluir a primeira linha, você deve escrever todas as outras linhas do espaço do padrão no arquivo.

  • Você pode usar os seguintes comandos para fazer o que quiser em segundos.
  • Isso gravará o arquivo inteiro em uma matriz.
  • Remova a primeira linha à medida que a despeja novamente no arquivo.

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

Apenas mude largefilepara o nome do seu arquivo.


Por que não usar sed -i 1d largefile? Isso funciona mesmo para os ficheiros maiores do que RAM + swap de
Tino

0

Para remover um elemento em um índice específico, podemos usar unsete copiar para outra matriz. Apenas unsetnão é necessário neste caso. Como unsetnão remove o elemento, apenas define uma string nula para o índice específico na 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]}"

Saída é

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
Isso seria muito melhor se houvesse algo para explicar como funciona e não apenas um blob de código. E o que há com as tiras na parte inferior?
um CVn 08/10

3
Sério, você está correto. Parece que foi escrito por um hooligan, mas obrigado. Eu realmente só consigo esgueirar isso entre os dias de servir hambúrgueres.
MageProspero

Se qualquer elemento de q tiver espaços, isso o dividirá em vários elementos.
William Everett
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.